javascript - 从两个不同的 useEffect 调用一个方法(改变状态)
问题描述
我正在玩 React Hooks,从两个不同的 useEffect 调用一个方法(改变状态)。给出以下代码:
function App() {
const [clicked, setClicked] = useState(false);
/**
* Listen for clicked changes. When clicked changes to true,
* allow setCounterAndSetUrlHash to do it's thing, before accpeting
* the next click. So the clicked flag is simply a valve, that opens
* after two seconds.
*/
useEffect(() => {
if (clicked) {
setCounterAndSetUrlHash(counter + 1);
setTimeout(() => {
setClicked(false);
}, 2000);
}
}, [clicked]);
const [counter, setCounter] = useState(0);
/**
* Listen for changes in the URL hash. When the user presses
* the back button in the browser toolbar, decrement the
* counter value.
*/
useEffect(() => {
window.onhashchange = () => {
const value = Number(window.location.hash.replace("#", ""));
// must be number
if (typeof value === "number" && value % 1 === 0) {
if (counter - 1 === value) {
setCounterAndSetUrlHash(counter - 1);
}
}
};
});
/**
* Set a new counter value and apply the same value
* to the URL hash. I want to reuse this function
* in both useEffect above.
*/
const setCounterAndSetUrlHash = value => {
setCounter(value);
if (value === 0) {
window.location.hash = "";
} else {
window.location.hash = String(value);
}
};
return (
<div className="App">
<p>Clicked: {String(clicked)}</p>
<p>Counter: {counter}</p>
<button type="button" onClick={() => setClicked(true)}>
Click me
</button>
</div>
);
}
实际代码: https ://codesandbox.io/s/dreamy-shadow-7xesm
该代码实际上正在工作。但是我收到了这个警告..
React Hook useEffect 缺少依赖项:'counter'。包括它或删除依赖数组。(react-hooks/exhaustive-deps)
..我不确定如何在保持当前功能的同时符合这一要求。当我向依赖项添加计数器时,我最终会出现一个无限循环。
解决方案
您的第一个效果使用counter
状态变量,但它的依赖项列表不包括它。将其包含在依赖项列表中将创建无限循环。
您可以counter
通过在setCounter
.
function App() {
const [clicked, setClicked] = useState(false);
/**
* Listen for clicked changes. When clicked changes to true,
* allow setCounterAndSetUrlHash to do it's thing, before accpeting
* the next click. So the clicked flag is simply a valve, that opens
* after two seconds.
*/
useEffect(() => {
if (clicked) {
incrCounter(1);
setTimeout(() => {
setClicked(false);
}, 2000);
}
}, [clicked]);
const [counter, setCounter] = useState(0);
/**
* Listen for changes in the URL hash. When the user presses
* the back button in the browser toolbar, decrement the
* counter value.
*/
useEffect(() => {
window.onhashchange = () => {
const value = Number(window.location.hash.replace("#", ""));
// must be number
if (typeof value === "number" && value % 1 === 0) {
if (counter - 1 === value) {
incrCounter(- 1);
}
}
};
});
useEffect(() => {
if (counter === 0) {
window.location.hash = "";
} else {
window.location.hash = String(counter);
}
}, [counter])
/**
* Set a new counter value and apply the same value
* to the URL hash. I want to reuse this function
* in both useEffect above.
*/
const incrCounter = delta => {
setCounter(value => value + delta);
};
return (
<div className="App">
<p>Clicked: {String(clicked)}</p>
<p>Counter: {counter}</p>
<button type="button" onClick={() => setClicked(true)}>
Click me
</button>
</div>
);
}