reactjs - 反应自定义钩子没有获得新的价值
问题描述
我仍在尝试了解 React Hooks 的工作原理。在构建这个自定义 Hook 时,我注意到一个特殊的行为:
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
总是将原始值输出到控制台。
示例用法:
应用程序.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>
);
};
脚步:
- 点击Increment
- 点击Print-> 控制台:
print value: 0
- 滚动 -> 控制台:
print value: hello
注意是第 3 步,值仍然是hello
。滚动时如何获得要打印的正确值?
解决方案
您需要从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];
};
推荐阅读
- variables - golang 变量替换
- protocol-buffers - 如何理解协议缓冲区 Varint 规则?
- c++ - 如何在 Visual Studio (c++) 中从 MySql 数据库中读取数据?
- node.js - 在 Linux 中覆盖 Electron App 的默认协议客户端
- python - Pip 安装包在导入时显示错误
- c# - 使用 .Net Standard 泛型参数对 mscorlib 泛型类型调用 DynamicMethod 会导致 MissingMethodException
- r - 对一些数据点进行聚类总是聚集在一起
- python - 从 Pandas 中的两个不同行解析日期
- spring-boot - SpringBoot:Eureka 服务器未发现 OAuth2 安全微服务
- jenkins - 删除 Jenkins 工作区中动态创建的文件夹名称