我有一个状态(页面)),我想改变每次点击一些按钮。setPagePage的值不会改变每次调用。
代码清晰:
const [page, setPage] = useState<number>(1);
useEffect(() => {
document.querySelectorAll('button').forEach((e) => {
e.addEventListener("click", () => {
setPage(parseInt(e.textContent ?? "1")); // this line executes but page value doesn't change
setTimeout(() => {
setTimeout(() => {
// irrelevant code
}, 10);
}, 200);
});
});
}, []);
由于您的useEffect()
的依赖数组是一个空数组,因此它永远不会使用page
的初始值进行多次计算。您需要将page
添加到依赖项数组中,但这将引入另一个问题,因为每次page
的值发生变化时都要添加新的事件侦听器。要处理这个问题,您需要添加一个由useEffect()
返回的清理函数,该函数将删除现有的事件侦听器:
const [page, setPage] = useState(1);
// A reference to the function we want to add and remove
const clickHandler = () => {
setPage(parseInt(e.textContent ?? "1")); // this line executes but page value doesn't change
setTimeout(() => {
setTimeout(() => {
// irrelevant code
}, 10);
}, 200);
}
useEffect(() => {
// Every time `page` changes, set events up with the new value of `page`
document.querySelectorAll('button').forEach((e) => {
e.addEventListener("click", clickHandler);
});
return () => {
// Clean up the existing event listeners using the old value of `page`
document.querySelectorAll('button').forEach((e) => {
e.removeEventListener("click", clickHandler);
});
}
}, [page]);
正如其他人所提到的,这段代码仍然是一个反模式,因为您正在脱离React(通过useEffect),直接在DOM上添加事件侦听器。你可能不需要Effect