更新 09/11/2020
不再需要此解决方案[email protected] /cdn-cgi/l/email-protection
以上。
Now useMemo
and useCallback
可以安全地接收引用类型作为依赖项。#19590 https://github.com/facebook/react/pull/19590
function MyComponent() {
const foo = ['a', 'b', 'c']; // <== This array is reconstructed each render
const normalizedFoo = useMemo(() => foo.map(expensiveMapper), [foo]);
return <OtherComponent foo={normalizedFoo} />
}
这是如何安全稳定(规范化)回调的另一个示例
const Parent = () => {
const [message, setMessage] = useState('Greetings!')
return (
<h3>
{ message }
</h3>
<Child setter={setMessage} />
)
}
const Child = ({
setter
}) => {
const stableSetter = useCallback(args => {
console.log('Only firing on mount!')
return setter(args)
}, [setter])
useEffect(() => {
stableSetter('Greetings from child\'s mount cycle')
}, [stableSetter]) //now shut up eslint
const [count, setCount] = useState(0)
const add = () => setCount(c => c + 1)
return (
<button onClick={add}>
Rerender {count}
</button>
)
}
现在具有稳定签名的引用类型,例如来自useState
or useDispatch
可以安全地在效果内使用而无需触发exhaustive-deps
即使来自props
---
旧答案
dispatch
来自习俗hook
因此它没有稳定的签名,因此会在每次渲染时发生变化(引用相等)。通过将处理程序包装在useCallback
hook
const [foo, dispatch] = myCustomHook()
const stableDispatch = useCallback(dispatch, []) //assuming that it doesn't need to change
useEffect(() =>{
stableDispatch(foo)
},[stableDispatch])
useCallback
and useMemo
是辅助钩子,主要目的是添加额外的层依赖性检查以保证同步性。通常您想与useCallback
以确保稳定的签名prop
你知道如何改变,而 React 不会。
A function
(引用类型)通过props
例如
const Component = ({ setParentState }) =>{
useEffect(() => setParentState('mounted'), [])
}
假设您有一个子组件,在安装时必须在父组件中设置某种状态(不常见),上面的代码将生成一个关于未声明依赖项的警告useEffect
,所以让我们声明setParentState
作为 React 检查的依赖项
const Component = ({ setParentState }) =>{
useEffect(() => setParentState('mounted'), [setParentState])
}
现在,此效果在每个渲染上运行,不仅在安装时运行,而且在每次更新时运行。发生这种情况是因为setParentState
is a function
每次函数都会重新创建Component
被叫。你懂的setParentState
不会随着时间的推移改变它的签名,所以可以安全地告诉 React。通过将原始助手包装在useCallback
您正在这样做(添加另一个依赖项检查层)。
const Component = ({ setParentState }) =>{
const stableSetter = useCallback(() => setParentState(), [])
useEffect(() => setParentState('mounted'), [stableSetter])
}
就这样吧。现在React
知道stableSetter
不会在生命周期内更改它的签名,因此效果不需要不必要地运行。
附注useCallback
它也被用来像useMemo
,优化昂贵的函数调用(记忆)。
的两个主要目的useCallback
are