在回调内部调用时,反应 useState 不能正确更新
react useState don't update properly when it's called inside callback
我要计算加载的 api。我用的是函数组件。
function Screen(props) {
const [count, setCount] = useState(0)
useEffect(() => {
loadData();
() => { return null; }
}, [])
const loadData = () => {
axios({ url: API_BASE_URL + 'countries', method: 'get' }).then((res)=>{
setCount(count+1)
})
axios({ url: API_BASE_URL + 'regions', method: 'get' }).then((res)=>{
setCount(count+1)
})
}
useEffect(() => {
console.info(count) // this shows 0, 1, it never be 2
}, [count])
return <div></div>
}
我的代码有什么问题?我认为它最后应该打印 2
谢谢
count
被传递给 then
的闭包 捕获为 作为 0
。实际上,您正在调用 setCount(0 + 1)
。可以在此处找到非常详尽的解释:https://overreacted.io/a-complete-guide-to-useeffect/
这是您的代码的更新版本,它修复了问题:
import React, { useCallback, useEffect, useState } from 'react';
const fakeApi = (delay = 400, val = null): Promise<typeof val> => new Promise(resolve => {
setTimeout(resolve, delay, val);
});
const Count: React.FC = () => {
const [count, setCount] = useState(0);
const loadData = useCallback(() => {
fakeApi(1000).then(() => {
setCount(count => count + 1); // use the function form of setState to get the current state value without being *dependent* on it.
});
fakeApi(2000).then(() => {
setCount(count => count + 1); // same as above.
});
}, []); // no dependencies => loadData is constant
useEffect(() => {
loadData();
}, [loadData]); // dependent on loadData, but that changes only once (first render, see above).
// note: you could move loadData inside the effect to reduce some code noise. Example:
//
// useEffect(() => {
// const loadData = () => {
// fakeApi(1000).then(() => {
// setCount(count => count + 1);
// });
//
// fakeApi(2000).then(() => {
// setCount(count => count + 1);
// });
// };
//
// loadData();
// }, []);
return (
<div>{count}</div>
);
};
export default Count;
演示:https://codesandbox.io/s/focused-sun-0cz6u?file=/src/App.tsx
我要计算加载的 api。我用的是函数组件。
function Screen(props) {
const [count, setCount] = useState(0)
useEffect(() => {
loadData();
() => { return null; }
}, [])
const loadData = () => {
axios({ url: API_BASE_URL + 'countries', method: 'get' }).then((res)=>{
setCount(count+1)
})
axios({ url: API_BASE_URL + 'regions', method: 'get' }).then((res)=>{
setCount(count+1)
})
}
useEffect(() => {
console.info(count) // this shows 0, 1, it never be 2
}, [count])
return <div></div>
}
我的代码有什么问题?我认为它最后应该打印 2 谢谢
count
被传递给 then
的闭包 捕获为 作为 0
。实际上,您正在调用 setCount(0 + 1)
。可以在此处找到非常详尽的解释:https://overreacted.io/a-complete-guide-to-useeffect/
这是您的代码的更新版本,它修复了问题:
import React, { useCallback, useEffect, useState } from 'react';
const fakeApi = (delay = 400, val = null): Promise<typeof val> => new Promise(resolve => {
setTimeout(resolve, delay, val);
});
const Count: React.FC = () => {
const [count, setCount] = useState(0);
const loadData = useCallback(() => {
fakeApi(1000).then(() => {
setCount(count => count + 1); // use the function form of setState to get the current state value without being *dependent* on it.
});
fakeApi(2000).then(() => {
setCount(count => count + 1); // same as above.
});
}, []); // no dependencies => loadData is constant
useEffect(() => {
loadData();
}, [loadData]); // dependent on loadData, but that changes only once (first render, see above).
// note: you could move loadData inside the effect to reduce some code noise. Example:
//
// useEffect(() => {
// const loadData = () => {
// fakeApi(1000).then(() => {
// setCount(count => count + 1);
// });
//
// fakeApi(2000).then(() => {
// setCount(count => count + 1);
// });
// };
//
// loadData();
// }, []);
return (
<div>{count}</div>
);
};
export default Count;
演示:https://codesandbox.io/s/focused-sun-0cz6u?file=/src/App.tsx