React useEffect为何在状态初始值为null时仍触发日志?
为什么未修改的null状态变量会被useUpdateLogger打印?
问题场景
你定义了状态变量:
const [fromAirport, setFromAirport] = useState<Airport | null>(null);
同时编写了自定义Hook用于监听值变化并打印:
export const useUpdateLogger = (value: any) => { useEffect(() => { console.log(value); }, [value]); };
通过useUpdateLogger(fromAirport);调用后,发现即使从未修改过fromAirport,控制台依然打印了null,这是为什么?
原因解释
- useEffect的挂载执行特性:React中
useEffect的回调函数会在组件挂载完成后自动执行一次,这是默认行为,和依赖项是否发生“变化”无关。你的fromAirport初始值是null,组件挂载时依赖数组[value]对应的就是这个初始值,所以回调会触发,打印出null。 - 依赖项的“变化”是相对前后渲染周期:依赖项的对比是针对组件的两次渲染而言。第一次渲染没有前序参考值,React会直接执行
useEffect回调;只有后续渲染中,依赖项和上一次的值不同时,才会再次触发。你没修改过状态,所以只会触发这一次挂载时的打印。
可选优化(跳过初始打印)
如果希望Hook只在**值真正发生变化(从初始值开始改变)**时打印,可以给自定义Hook增加初始渲染的判断:
export const useUpdateLogger = (value: any) => { const firstRender = useRef(true); useEffect(() => { // 跳过第一次挂载时的执行 if (firstRender.current) { firstRender.current = false; return; } console.log(value); }, [value]); };
这样就能只在fromAirport从null变为其他值,或者在非null值之间切换时才打印。
内容的提问来源于stack exchange,提问作者Amos Machora
相关产品推荐
相关产品推荐

