我目前正在useEffect内放置一个API GET请求调用。这里的想法是每次状态被修改时都要"重新渲染"列表。
const[superheroes, setSuperheroes] = useState([]);
useEffect(() => {
apiCall('/superheroes', { method: 'GET'})
.then(response => {
response.json().then(response => {
setSuperheroes(response);
}).catch(x=> console.log("ERROR: " + x))
})
}, [superheroes])
简单地这样做将导致无限调用循环,即使superheroes
状态尚未改变。
我能得到一个清楚的解释为什么会发生这种情况吗?
编辑:澄清。我故意不使用空数组作为useEffect()的第二个参数,因为我不想运行它一次。当您在useEffect中设置一个新数组(也是一个对象)时,会发生这种情况
function DoSomethingCrazy() {
const [superheroes, setSuperheroes] = React.useState([]);
React.useEffect(() => {
console.log("i have arrived at the party!");
setSuperheroes(["123123"]);
}, [superheroes]);
return <div>stuff goes here</div>;
}
const rootElement = document.getElementById("root");
ReactDOM.render(<DoSomethingCrazy />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root"></div>
尝试将一个空数组放到useEffect中,这样它只运行一次:
useEffect(() => {
apiCall("/superheroes", { method: "GET" }).then((response) => {
response
.json()
.then((response) => {
setSuperheroes(response);
})
.catch((x) => console.log("ERROR: " + x));
});
}, []);
每次超级英雄被改变时都会触发此效果。因为useEffect总是第一次执行,然后根据代码在ajax调用时获得的依赖数组,并且响应的superheroes被setSuperheroes更改,然后因为是useEffect的依赖项,整个过程将再次发生。
这里你没有重新渲染,你只是通过ajax重新获取。
React使用shallow compare
比较新状态和当前状态
当API调用成功时,setSuperheroes
将调用一个新的数组,并且state将有一个新的值。对于shallow compare
,新状态总是不同于当前状态,所以组件总是重新渲染。