为什么我的ReactJs循环下拉列表会自动调用多次


import React, { useState, useEffect } from 'react';
import axios from 'axios';
const App = () => {
const [num, setNum] = useState();
const [name, setName] = useState();
const [moves, setMoves] = useState();

useEffect(() => {
async function pokemonAPI() {
const getPokemon = await axios.get(`https://pokeapi.co/api/v2/pokemon/${num}`);
console.log(getPokemon.data.name);
setName(getPokemon.data.name);
setMoves(getPokemon.data.moves.length);
}
pokemonAPI();

// this function call many times automatically how can I fix this.  
**function dropDown() { // this function call many times itself
for (var y = 0; y <101; y++) {
document.getElementById("100dropdown").innerHTML += ("<option value =" + y + " >" + y + "</option>");
}
}
dropDown();**   
});
// its works fine on first reload of page but when i choose any number this function call it many times 
return (
<>
<div className="main_div">
<h1 className="choose_value">
Please Choose your <strong>  Pokemon </strong> Value <br />
<select name="100dropdown" id="100dropdown" value={num} onChange={(event) => {
setNum(event.target.value);
}}>

</select>
</h1>
<div className="pokemonList">
<h1>You've choose <span style={{ color: 'green' }}> {num} </span> value</h1>
<h1>Your Pokemon is <span style={{ color: 'red' }}> {name}</span></h1>
<h1>Your Pokemon has <span style={{ color: 'blue' }}> {moves}</span> moves </h1>
</div>
</div>
</>
);
}
export default App;

问题

useEffect缺少依赖项,因此每次组件渲染时都会触发效果回调。pokemonAPI会更新状态,因此每次都会触发一个新的渲染。这将创建一个渲染循环,因此每次渲染也将调用dropDown

此外,我看不出有任何理由应该在useEffect中声明dropDown。它呈现静态数据并更改DOM,这是React中的反模式。

解决方案

修复依赖关系,添加GET请求中使用的num,并删除dropDown函数:

useEffect(() => {
async function pokemonAPI() {
const getPokemon = await axios.get(`https://pokeapi.co/api/v2/pokemon/${num}`);
console.log(getPokemon.data.name);
setName(getPokemon.data.name);
setMoves(getPokemon.data.moves.length);
}
pokemonAPI();
}, [num]); // <-- add dependency array!

如果你需要运行更多的效果,那么添加任何丢失的依赖项,你的linter可能也会抱怨。

使用id="100dropdown"在元素内部计算并呈现JSX中的选择选项。

<select
name="100dropdown"
id="100dropdown"
value={num}
onChange={(event) => setNum(event.target.value)}
>
{Array.from({ length: 100 }, (v, i) => i)).map(i => (
<option key={i} value={i}>{i}</option>
))}
</select>

最新更新