通常在使用 React+Typescript 编写组件时,我想在其中一个 Prop 上触发 useEffect Hook 。例如,考虑一个为每次连续鼠标点击执行不同功能的按钮:
export function ActionButton({clickActions}: {clickActions: (() => void)[]}) {
const [clicked, setClicked] = useState(0);
useEffect(() => {
if (clickActions.length > 0 && clickActions[clicked % clickActions.length]) {
clickActions[clicked % clickActions.length]();
}
}, [clicked, clickActions])
return <button onClick={() => setClicked(clicked => clicked + 1)}/>
}
在这种情况下,该组件的客户端需要意识到他们需要以某种方式阻止 clickActions
从在每个渲染上成为不同的实例。例如,它可以只是一个常数,或者使用 useMemo
来内存。 .是否有让我的客户意识到这一点的最佳做法?当违反此规则时,是否有办法触发编译时错误?
注意:我意识到这种特殊情况可以在不使用
useEffect
的情况下解决。 ,但这只是一个简单的例子来说明模式。我对解决这个特定问题不感兴趣,而是对如何解决一般问题感兴趣。
最佳答案
您无法通过 TypeScript 诡计来强制执行 clickActions
每次父级渲染时都无法更改。
但是,您可以简单地删除 clickActions
来自 useEffect
的依赖列表。一般来说,这样做时你必须小心,但在这种情况下,它是安全的,因为你传递给 useEffect
的回调clicked
时同步执行一个 Action 更改,这意味着回调将引用最近的 clickActions
当它需要它时。
这类似于 sample
RxJS 中的运算符;即clickActions
被 clicked
采样.
useEffect(() => {
if (clickActions.length > 0 && clickActions[clicked % clickActions.length]) {
clickActions[clicked]();
}
}, [clicked])
另请注意,即使 parent 使用 useMemo
, 不保证不会重新创建 clickActions
在 React 选择的时候:You may rely on
useMemo
as a performance optimization, not as a semantic guarantee. In the future, React may choose to “forget” some previously memoized values and recalculate them on next render, e.g. to free memory for offscreen components. Write your code so that it still works withoutuseMemo
— and then add it to optimize performance.
(见 useMemo docs)
可以肯定地假设
useCallback
带有类似的警告,尽管文档中没有特别提及。
关于reactjs - 在 useEffect 或类似中使用指示 prop 的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63314762/