我仍在努力思考React Hooks的工作原理。在构建此自定义挂钩时,我注意到了一个奇怪的行为:
const useCustomHook = () => {
const [value, setValue] = useState('hello');
useEffect(() => {
window.addEventListener('scroll', print, false);
return () => window.removeEventListener('scroll', print, false);
}, []);
const print = () => console.log('print value: ', value); // shows updated value when called directly but original value when scrolling
return [setValue, print];
};
print
输出到控制台的行为是特殊的。直接调用print
时,该值反映正确的更新值。但是滚动时,print
始终将原始值输出到控制台。
用法示例:
App.js
let counter = 0;
const App = () => {
const [setValue, print] = useCustomHook();
return (
<div style={{ margin: '50px auto 10000px' }}>
<button onClick={() => setValue(counter++)}>Increment</button>{' '}
<button onClick={print}>Print</button>
</div>
);
};
步骤:
print value: 0
print value: hello
注意是步骤3,该值仍为hello
。滚动时如何获得要打印的正确值?
答案 0 :(得分:3)
您需要从useEffect
中删除依赖项。
useEffect(() => {
window.addEventListener('scroll', print, false);
return () => window.removeEventListener('scroll', print, false);
}); // remove the empty array
如果将其设置为[]
,则将仅执行一次。
如果删除它,它将在每次更新时执行。
理想情况下,仅当useEffect
更改时,您才想重新评估value
中的代码。
然后,您可以将print
添加到依赖项数组中。
const useCustomHook = () => {
const [value, setValue] = useState(-1);
// useCallback will re-create the function only if 'value' changes
const print = useCallback(() => {
console.log('print value: ', value);
}, [value]);
// useEffect will be re-evaluated if 'print' changes
useEffect(() => {
window.addEventListener('scroll', print, false);
return () => window.removeEventListener('scroll', print, false);
}, [print]);
return [setValue, print];
};