英文:
Using useEffect in React to change API request
问题
点击按钮后,我没有获得新的宝可梦名称,而是显示为空白。
英文:
I am learning React hooks and made a project to display a random Pokemon name through https://pokeapi.co/docs/v2#pokemon by calling a random Pokemon ID. I'm not quite sure how to trigger the useEffect
to fetch after clicking on the button.
import './App.css';
import { useState, useEffect } from 'react';
function getNewPokemonId(pokemon){
pokemon = Math.floor(Math.random() * 1011);
console.log(pokemon)
return pokemon;
}
function App() {
const [pokemon , setNewPokemon] = useState(1);
useEffect(() => {
console.log("render");
const pokemonID = getNewPokemonId()
fetch(`https://pokeapi.co/api/v2/pokemon/${pokemonID}`)
.then((response) => response.json())
.then((json) =>
setNewPokemon(json)
);
}, []);
return (
<main>
<h1>
Random Pokemon Generator
</h1>
<section>
<button onClick={() => setNewPokemon(getNewPokemonId(pokemon))}>
New Pokemon
</button>
<h3>{pokemon?.name}</h3>
</section>
</main>
);
}
export default App;
After clicking on the button I don't get a new Pokemon name instead it is blank.
答案1
得分: 1
你可以定义一个函数来通过id获取Pokemon的数据,并在挂载时以及点击事件处理程序中调用它。
function App() {
const [pokemon, setNewPokemon] = useState();
const getPokemon = id => fetch(`https://pokeapi.co/api/v2/pokemon/${id}`).then(res => res.json()).then(d => setNewPokemon(d));
useEffect(() => {
console.log("render");
getPokemon(getNewPokemonId());
}, []);
return (
<main>
<h1>随机 Pokemon 生成器</h1>
<section>
<button onClick={() => getPokemon(getNewPokemonId())}>
新 Pokemon
</button>
<h3>{pokemon?.name}</h3>
</section>
</main>
);
}
请注意,上述代码是使用 JSX 编写的 React 组件,其中包含一个用于获取随机 Pokemon 数据的函数。
英文:
You can define a function to fetch the data for a Pokemon by id and call it on mount and in the click event handler.
function App() {
const [pokemon, setNewPokemon] = useState();
const getPokemon = id => fetch(`https://pokeapi.co/api/v2/pokemon/${id}`).then(res => res.json()).then(d => setNewPokemon(d));
useEffect(() => {
console.log("render");
getPokemon(getNewPokemonId());
}, []);
return (
<main>
<h1>Random Pokemon Generator</h1>
<section>
<button onClick={() => getPokemon(getNewPokemonId())}>
New Pokemon
</button>
<h3>{pokemon?.name}</h3>
</section>
</main>
);
}
答案2
得分: 1
我使用这个应用程序创建了一个沙盒:
沙盒链接 https://codesandbox.io/s/holy-morning-tkwtpv
import "./styles.css";
import { useState, useEffect } from "react";
function getNewPokemonId() {
const pokemon = Math.floor(Math.random() * 1011);
console.log(pokemon);
return pokemon;
}
export default function App() {
const [pokemon, setNewPokemon] = useState(1);
const fetchPokemon = async () => {
const response = await fetch(
`https://pokeapi.co/api/v2/pokemon/${getNewPokemonId()}`
);
const data = await response.json();
setNewPokemon(data);
};
useEffect(() => {
fetchPokemon();
}, []);
const handleOnClick = () => {
fetchPokemon();
};
return (
<div className="App">
<h1>随机宝可梦生成器</h1>
<section>
<button onClick={handleOnClick}>新宝可梦</button>
<h3>{pokemon?.name}</h3>
</section>
</div>
);
}
希望这对你有帮助。
英文:
I created a sandbox with this app working:
Sandbox https://codesandbox.io/s/holy-morning-tkwtpv
import "./styles.css";
import { useState, useEffect } from "react";
function getNewPokemonId() {
const pokemon = Math.floor(Math.random() * 1011);
console.log(pokemon);
return pokemon;
}
export default function App() {
const [pokemon, setNewPokemon] = useState(1);
const fetchPokemon = async () => {
const response = await fetch(
`https://pokeapi.co/api/v2/pokemon/${getNewPokemonId()}`
);
const data = await response.json();
setNewPokemon(data);
};
useEffect(() => {
fetchPokemon();
}, []);
const handleOnClick = () => {
fetchPokemon();
};
return (
<div className="App">
<h1>Random Pokemon Generator</h1>
<section>
<button onClick={handleOnClick}>New Pokemon</button>
<h3>{pokemon?.name}</h3>
</section>
</div>
);
}
I hope that this could help
答案3
得分: 0
在useEffect
的末尾添加[]
将意味着它只会在页面加载开始时触发一次。
添加[pokemon]
将使useEffect
在变量更改时每次运行。
英文:
having []
at the end of the useEffect will mean it will only trigger once at the start of the page load.
having this: [pokemon]
will make the useEffect run every time the variable changes.
答案4
得分: 0
这不是百分之百可靠的,但这是一个开始。你应该将 Pokémon 数据存储到状态中,而不是 ID。确保正确设置状态。
注意
如果你注意到,ID 从 1010 跳到了 10001。
所以随机范围在技术上应该是:1-1010,10001-10271。
示例
这是一个 Pokémon 随机生成器的基本工作示例。它相当灵敏。
const { useCallback, useEffect, useState } = React;
// 比 Math.random 更好的伪随机数生成器
// 来源:https://stackoverflow.com/a/47593316/1762224
const mulberry32 = (seed) =>
() => {
let t = seed += 0x6D2B79F5;
t = Math.imul(t ^ t >>> 15, t | 1);
t ^= t + Math.imul(t ^ t >>> 7, t | 61);
return ((t ^ t >>> 14) >>> 0) / 4294967296;
}
const rand = mulberry32(performance.now()); // 以当前时间为种子
const randomInt = (min, max) => Math.floor(rand() * (max - min + 1)) + min;
const toTitleCase = (str = '') =>
str.replace(/\w\S*/g, (txt) =>
txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase());
// 参考:https://pokeapi.co/api/v2/pokemon?offset=0&limit=2000
const ranges = [[1, 1010], [10001, 10271]]; // 分布:(1010, 271)
const getRandomId = () => {
const which = randomInt(1, 5);
const range = ranges[which === 5 ? 1 : 0]; // 20% 概率选择范围 #2
return randomInt(...range);
};
const apiBaseUrl = 'https://pokeapi.co/api/v2';
const App = () => {
const [pokemonData, setPokemonData] = useState({ id: 0, name: '', sprites: [] });
const [loading, setLoading] = useState(false);
const [errorText, setErrorText] = useState('');
const randomize = useCallback(() => {
setErrorText('');
setLoading(true);
const randId = getRandomId();
fetch(`${apiBaseUrl}/pokemon/${randId}`)
.then(res => res.json())
.then(data => {
setPokemonData(data);
})
.catch(() => {
setErrorText(`找不到 ID 为 ${randId} 的 Pokémon!`);
})
.finally(() => setLoading(false));
}, []);
useEffect(() => {
randomize();
}, []);
return (
<main>
<h1>随机 Pokémon 生成器</h1>
<section>
<button disabled={loading} onClick={randomize}>新的 Pokémon</button>
{errorText !== '' && <p style={{color:'red'}}>{errorText}</p>}
<h3>[{pokemonData.id}] {toTitleCase(pokemonData.name)}</h3>
<img src={pokemonData.sprites.front_default} />
</section>
</main>
);
};
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
这是一个基本工作的 Pokémon 随机生成器示例。它相当灵敏。
英文:
It' not fool-proof, but it's a start. You should store the Pokémon data into the state, not the ID. Make sure you properly set the state as well.
Note
If you notice, the IDs jump from 1010 to 10001.
So the random range should technically be: 1-1010, 10001-10271.
Example
Here is an basic working example of a Pokémon randomizer. It's fairly responsive.
<!-- begin snippet: js hide: false console: true babel: true -->
<!-- language: lang-js -->
const { useCallback, useEffect, useState } = React;
// Better PRNG than Math.random
// Source: https://stackoverflow.com/a/47593316/1762224
const mulberry32 = (seed) =>
() => {
let t = seed += 0x6D2B79F5;
t = Math.imul(t ^ t >>> 15, t | 1);
t ^= t + Math.imul(t ^ t >>> 7, t | 61);
return ((t ^ t >>> 14) >>> 0) / 4294967296;
}
const rand = mulberry32(performance.now()); // Seeded with current time
const randomInt = (min, max) => Math.floor(rand() * (max - min + 1)) + min;
const toTitleCase = (str = '') =>
str.replace(/\w\S*/g, (txt) =>
txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase());
// Refer to: https://pokeapi.co/api/v2/pokemon?offset=0&limit=2000
const ranges = [[1, 1010], [10001, 10271]]; // Distribution: (1010, 271)
const getRandomId = () => {
const which = randomInt(1, 5);
const range = ranges[which === 5 ? 1 : 0]; // 20% for range #2
return randomInt(...range);
};
const apiBaseUrl = 'https://pokeapi.co/api/v2';
const App = () => {
const [pokemonData, setPokemonData] = useState({ id: 0, name: '', sprites: [] });
const [loading, setLoading] = useState(false);
const [errorText, setErrorText] = useState('');
const randomize = useCallback(() => {
setErrorText('');
setLoading(true);
const randId = getRandomId();
fetch(`${apiBaseUrl}/pokemon/${randId}`)
.then(res => res.json())
.then(data => {
setPokemonData(data);
})
.catch(() => {
setErrorText(`Pokemon with ID of ${randId} not found!`);
})
.finally(() => setLoading(false));
}, []);
useEffect(() => {
randomize();
}, []);
return (
<main>
<h1>Random Pokemon Generator</h1>
<section>
<button disabled={loading} onClick={randomize}>New Pokemon</button>
{errorText !== '' && <p style={{color:'red'}}>{errorText}</p>}
<h3>[{pokemonData.id}] {toTitleCase(pokemonData.name)}</h3>
<img src={pokemonData.sprites.front_default} />
</section>
</main>
);
};
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
<!-- language: lang-html -->
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论