诸如useEffect
,useMemo
,useCallback
之类的某些React Hooks API具有第二个参数:输入数组:
useEffect(didUpdate, inputs);
如官方文件所述:
@请参阅Conditionally firing an effect
这样,如果其中一项输入发生更改,则始终会重新创建效果。
效果函数中引用的每个值也应出现在输入数组中。
因此我们可以看到,inputs
数组承担两项职责。
在大多数情况下,它们运行正常。但有时它们会发生冲突。
例如,我有一个小计数程序,它可以完成两件事:
单击按钮,然后将计数加1。
每5秒钟将计数发送到服务器。
代码和框:
https://codesandbox.io/s/k0m1mq9v
或在此处查看代码:
import { useState, useEffect, useCallback } from 'react';
function xhr(count) {
console.log(`Sending "${count}" to my server.`);
// TODO send count to my server by XMLHttpRequest
}
function add1(n) {
return n + 1;
}
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
// Handle click to increase count by 1
const handleClick = useCallback(
() => setCount(add1),
[],
);
// Send count to server every 5 seconds
useEffect(() => {
const intervalId = setInterval(() => xhr(count), 5000);
return () => clearInterval(intervalId);
}, []);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={handleClick}>
Click me
</button>
</div>
);
}
export default Example;
运行此代码时,我总是将count = 0
发送到服务器,因为我没有将count
传递给useEffect
。
但是,如果我将count
传递给useEffect
,则每次单击按钮时,我的setInterval
将被清除,并且整个回调将重新创建。
我认为也许还有另一个范式可以实现我没有想到的目标。如果不是,那就是inputs
数组的冲突。
答案 0 :(得分:0)
React的回复:
可能会实施更好的解决方案,但不是现在。
但是生活会继续下去,因此像this这样的解决方法可能会有所帮助:
const [count, setCount] = useState(0);
const countRef = useRef(count);
useEffect(() => {
countRef.current = count
}, [count]);
答案 1 :(得分:0)
useRef()
可以解决您的问题。我认为这是一个很好的解决方案:code in sandbox
function App() {
const [count, setCount] = useState(0);
// ***** Initialize countRef.current with count
const countRef = useRef(count);
const handleClick = useCallback(() => setCount(add1), []);
// ***** Set countRef.current to current count
// after comment https://github.com/facebook/react/issues/14543#issuecomment-452996829
useEffect(() => (countRef.current = count));
useEffect(() => {
// ***** countRef.current is xhr function argument
const intervalId = setInterval(() => xhr(countRef.current), 5000);
return () => clearInterval(intervalId);
}, []);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={handleClick}>Click me</button>
</div>
);
}
编辑
评论后:https://github.com/facebook/react/issues/14543#issuecomment-452996829