如何防止内联函数绑定到旧状态值



在使用钩子的 React 组件的项目中,我试图了解如何正确避免调用绑定到旧状态值的回调。下面的示例说明了该问题(但不是我正在处理的代码(。

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
const Message = () => {
const [message, setMessage] = useState("");
function doStuff() {
console.log(message);
}
useEffect(() => {
setInterval(doStuff, 1000)
}, []);
return (
<div>
<input
type="text"
value={message}
placeholder="Enter a message"
onChange={e => setMessage(e.target.value)}
/>
<p>
<strong>{message}</strong>
</p>
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<Message />, rootElement);

这里的问题是,setInterval将保持doStuff函数与第一次(也是唯一一次(效果时的状态相同。当时message状态为空,因此,间隔函数将每秒打印一个空字符串,而不是文本框内的实际消息。

在我的真实代码中,我遇到了应该在组件内部触发函数调用的外部事件,并且它们遇到了同样的问题。

我该怎么办?

您应该useCallback并将其作为依赖项传递。

const doStuff = useCallback(() => {
console.log(message);
}, [message]);
useEffect(() => {
const interval = setInterval(doStuff, 1000);
return () => clearInterval(interval); // clean up
}, [doStuff]);

在这里,当message更新时,它将在doStuff中具有新值

你也可以把它放在它自己的钩子里。我的生产代码中有这个

/**
* A react hook for setting up an interval
* @param handler - Function to execute on interval
* @param interval - interval in milliseconds
* @param runImmediate - If the function is executed immediately
*/
export const useInterval = (handler: THandlerFn, interval: number | null, runImmediate = false): void => {
const callbackFn = useRef<THandlerFn>()
// Update callback function
useEffect((): void => {
callbackFn.current = handler
}, [handler])
// Setup interval
useEffect((): (() => void) | void => {
const tick = (): void => {
callbackFn.current && callbackFn.current()
}
let timerId: number
if (interval) {
if (runImmediate) {
setTimeout(tick, 0)
}
timerId = setInterval(tick, interval)
return (): void => {
clearInterval(timerId)
}
}
}, [interval, runImmediate])
}

相关内容

  • 没有找到相关文章

最新更新