在 React 中使用 useEffect 无限循环
Infinite loop with useEffect in React
这是我的组件:
import React, { useState, useEffect } from "react";
export default function App() {
const [countriesArray, setCountriesArray] = useState([]);
useEffect(() => {
getCountriesArray();
}, []);
const getCountriesArray = async () => {
try {
let response = await fetch(
"https://coronavirus-19-api.herokuapp.com/countries"
);
if (response.status === 200) {
const newCountriesArray = [...countriesArray];
const data = await response.json();
await data.forEach(item => newCountriesArray.push(item.country));
setCountriesArray(newCountriesArray);
} else {
setErrorStatus(true);
console.error("Error status");
}
} catch (err) {
console.error(err);
}
};
const optionItems = countriesArray.map((item) =>
<option key={item}>{item}</option>
)
return (
<div className="App">
<select>{optionItems}</select>
</div>
);
}
在 select 中,我在安装组件时得到了国家的名称,但在控制台中我有一个循环错误消息:
Warning: Encountered two children with the same key, `Total:`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.
in select (at App.js:36)
in div (at App.js:35)
in App
in StrictMode (at src/index.js:8)
但是我使用空数组作为useEffect的第二个参数,只在挂载组件时执行它
您可以这样使用地图本身提供的密钥:
const optionItems = countriesArray.map((item, key) =>
<option key={key}>{item}</option>
)
这应该可以解决您的问题。
顺便说一句,这不是无限循环问题,它是映射函数中的重复键。
该错误与效果的依赖数组无关。问题是 item.country 在该数据中不是唯一的。 json 包括 7 个条目,其中 country
=== "Total:"
。
几种可能性:
1) 过滤掉重复项。如果您不关心那些 "Total:" 条目,这是最好的。
if (response.status === 200) {
const newCountriesArray = [...countriesArray];
const data = await response.json();
data.forEach(item => {
if (item.country !== "Total:") {
newCountriesArray.push(item.country)
}
});
setCountriesArray(newCountriesArray);
}
2) 使用不同的密钥。由于此数据没有唯一键,您可能需要使用数组的索引。请注意,如果您打算对此列表进行排序,这将不是一个好的选择。
const optionItems = countriesArray.map((item, index) =>
<option key={index}>{item}</option>
)
这是我的组件:
import React, { useState, useEffect } from "react";
export default function App() {
const [countriesArray, setCountriesArray] = useState([]);
useEffect(() => {
getCountriesArray();
}, []);
const getCountriesArray = async () => {
try {
let response = await fetch(
"https://coronavirus-19-api.herokuapp.com/countries"
);
if (response.status === 200) {
const newCountriesArray = [...countriesArray];
const data = await response.json();
await data.forEach(item => newCountriesArray.push(item.country));
setCountriesArray(newCountriesArray);
} else {
setErrorStatus(true);
console.error("Error status");
}
} catch (err) {
console.error(err);
}
};
const optionItems = countriesArray.map((item) =>
<option key={item}>{item}</option>
)
return (
<div className="App">
<select>{optionItems}</select>
</div>
);
}
在 select 中,我在安装组件时得到了国家的名称,但在控制台中我有一个循环错误消息:
Warning: Encountered two children with the same key, `Total:`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.
in select (at App.js:36)
in div (at App.js:35)
in App
in StrictMode (at src/index.js:8)
但是我使用空数组作为useEffect的第二个参数,只在挂载组件时执行它
您可以这样使用地图本身提供的密钥:
const optionItems = countriesArray.map((item, key) =>
<option key={key}>{item}</option>
)
这应该可以解决您的问题。
顺便说一句,这不是无限循环问题,它是映射函数中的重复键。
该错误与效果的依赖数组无关。问题是 item.country 在该数据中不是唯一的。 json 包括 7 个条目,其中 country
=== "Total:"
。
几种可能性:
1) 过滤掉重复项。如果您不关心那些 "Total:" 条目,这是最好的。
if (response.status === 200) {
const newCountriesArray = [...countriesArray];
const data = await response.json();
data.forEach(item => {
if (item.country !== "Total:") {
newCountriesArray.push(item.country)
}
});
setCountriesArray(newCountriesArray);
}
2) 使用不同的密钥。由于此数据没有唯一键,您可能需要使用数组的索引。请注意,如果您打算对此列表进行排序,这将不是一个好的选择。
const optionItems = countriesArray.map((item, index) =>
<option key={index}>{item}</option>
)