我有下面的代码片段。为什么fetchData
的极限总是0 ?如果我把console.log(limit)
移到这个函数外面它的值是正确的。此外,如果我不使用useState
,而是一个变量,而不是let limit = 0;
,那么它的工作如预期的
我还在useEffect中添加了limit作为依赖项,但它只是不断触发函数
const [currentData, setData] = useState([]);
const [limit, setLimit] = useState(0);
const fetchData = async () => {
console.log(limit);
const { data } = await axios.post(endpoint, {
limit: limit,
});
setData((state) => [...state, ...data]);
setLimit((limit) => limit + 50);
};
useEffect(() => {
fetchData();
window.addEventListener(`scroll`, (e) => {
if (bottomOfPage) {
fetchData();
}
});
}, []);
当您将一个空的依赖数组[]
传递给useEffect
时,效果只在初始渲染时运行一次:
如果你传递一个空数组([]),里面的道具和状态的效果将始终具有其初始值。
如果你想运行一个效果并且只清理一次(在mount和卸载),您可以传递一个空数组([])作为第二个参数。这告诉React你的效果不依赖于props的任何值或状态,因此它永远不需要重新运行。这不是一个特殊的处理Case -它直接遵循依赖数组的方式作品。
useEffect文档
limit
的初始状态是在useState
调用中定义的0
。将limit
添加为依赖项将导致每次limit
更改时都运行效果。
解决问题的一种方法是将fetchData
方法包装在useCallback
中,同时将limit
变量传递给依赖数组。
你可以将函数传递给useEffect的依赖数组,也可以从useEffect内部返回一个函数,该函数可以删除带有过时引用的事件侦听器。
你还应该添加一个加载变量,这样当用户滚动到底部时fetchData函数就不会被多次调用:
const [currentData, setData] = useState([]);
const [limit, setLimit] = useState(0);
const [loading, setLoading] = useState(false);
const fetchData = useCallback(async () => {
console.log(limit);
// Prevent multiple endpoint calls when scrolling near the end with a loading state
if (loading) {
return;
}
setLoading(true);
const { data } = await axios.post(endpoint, { limit });
setData((state) => [...state, ...data]);
setLimit((limit) => limit + 50);
setLoading(false);
}, [limit, loading]);
// Make the initial request on the first render only
useEffect(() => {
fetchData();
}, []);
// Whenever the fetchData function changes update the event listener
useEffect(() => {
const onScroll = (e) => {
if (bottomOfPage) {
fetchData();
}
};
window.addEventListener(`scroll`, onScroll);
// On unmount ask it to remove the listener
return () => window.removeEventListener("scroll", onScroll);
}, [fetchData]);