我正在尝试throttle
从lodash
功能组件中使用该方法,例如:
const App = () => {
const [value, setValue] = useState(0)
useEffect(throttle(() => console.log(value), 1000), [value])
return (
<button onClick={() => setValue(value + 1)}>{value}</button>
)
}
由于内部方法useEffect
在每次渲染时都重新声明,因此限制效果不起作用。
有没有人有一个简单的解决方案?
经过一段时间后,我相信setTimeout/clearTimeout
使用功能性助手(并将其移动到单独的自定义挂钩中)比使用功能性助手要容易得多。在稍后处理一个挑战之后,我们立即将其应用到useCallback
由于依赖关系更改而可以重新创建的挑战中,但是我们不想重置延迟运行。
下面的原始答案
您可能(可能需要)useRef
在渲染之间存储值。就像对计时器的建议一样
像这样
const App = () => {
const [value, setValue] = useState(0)
const throttled = useRef(throttle((newValue) => console.log(newValue), 1000))
useEffect(() => throttled.current(value), [value])
return (
<button onClick={() => setValue(value + 1)}>{value}</button>
)
}
至于useCallback
:
它可能也可以工作
const throttled = useCallback(throttle(newValue => console.log(newValue), 1000), []);
但是,如果我们尝试重新创建回调,则一旦value
更改:
const throttled = useCallback(throttle(() => console.log(value), 1000), [value]);
我们可能会发现它不会延迟执行:value
更改后,回调将立即重新创建并执行。
因此,我发现useCallback
在延迟运行的情况下不会提供明显的优势。由你决定。
[UPD]最初是
const throttled = useRef(throttle(() => console.log(value), 1000))
useEffect(throttled.current, [value])
但是这种方式throttled.current
已经value
通过闭包绑定到初始(0)。因此,即使在下一个渲染中也从未改变过。
因此,useRef
由于闭包功能,在将函数推入时要小心。