我正在尝试在功能组件中使用 lodash
中的 throttle
方法,例如:
const App = () => {
const [value, setValue] = useState(0)
useEffect(throttle(() => console.log(value), 1000), [value])
return (
<button onClick={() => setValue(value + 1)}>{value}</button>
)
}
由于每次渲染时都会重新声明useEffect
内部的方法,因此限制效果不起作用。
有人有一个简单的解决方案(无需将 throttle 实现移到组件之外)吗?
最佳答案
过了一段时间后,我确信使用 setTimeout/clearTimeout 自己处理事情(并将其移动到单独的自定义 Hook 中)比使用功能助手要容易得多。在我们将其应用于 useCallback
后,处理后面的一个会带来额外的挑战,因为依赖项更改可以重新创建,但我们不想重置延迟运行。
原始答案如下
你可能(并且可能需要)useRef
在渲染之间存储值。就像suggested for timers一样
类似的事情
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]);
我们可能会发现它不会延迟执行:一旦值
发生更改,回调就会立即重新创建并执行。
所以我认为 useCallback
在延迟运行的情况下并没有提供显着的优势。这取决于你。
[UPD]最初是
const throttled = useRef(throttle(() => console.log(value), 1000))
useEffect(throttled.current, [value])
但是这样 throttled.current
通过闭包绑定(bind)到初始值
(0)。所以即使在下一次渲染中它也从未改变。
因此,由于闭包功能,在将函数插入 useRef
时要小心。
关于reactjs - 如何通过 React Hook 使用 throttle 或去抖?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54666401/