我正在玩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缺少依赖项:“计数器”。要么 包括它或删除依赖项数组。 (反应钩/详尽的下降)
..而且我不确定在保持当前功能的情况下如何与之保持一致。当我添加计数器依赖项时,最终会出现无限循环。
答案 0 :(得分:1)
您的第一个效果使用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>
);
}
答案 1 :(得分:1)
尝试使用功能性setState setState((state, props) => stateChange)
useEffect(() => {
if (clicked) {
setCounterAndSetUrlHash(counter => counter + 1);
setTimeout(() => {
setClicked(false);
}, 2000);
}
}, [clicked]);
答案 2 :(得分:0)
要使用第一个计数器值解决$validatedData = $request->validate([
'titulo' => 'required|max:255',
'start' => 'required|max:255',
'starttime' => 'required|max:255', <----
'end' => 'required|max:255',
'endtime' => 'required|max:255', <----
'descripcion' => 'required|max:255',
'color' => 'required|max:255',
]);
$Calendarios=Calendarios::create($validatedData);
回调的问题,我建议将功能移至onhashchange
的回调。这也意味着按钮和哈希更改需要不同的功能。
还要在顶部和setCounter
之后设置变量和useState
定义,以便可以使用它们。如果只想让useEffect
运行一次,请设置一个空的依赖项数组;消除依赖关系将在每个渲染器上运行。
useEffect
答案 3 :(得分:0)
为第一个useEffect()添加计数器:
const [counter, setCounter] = useState(0);
useEffect(() => {
if (clicked) {
setCounterAndSetUrlHash(counter + 1);
setTimeout(() => {
setClicked(false);
}, 2000);
}
}, [clicked, counter]);