React Hook useState为何没有遵循传入的默认值参数?
问题原因
- useState初始值仅首次生效:React的
useStateHook 传入的初始值参数,仅会在组件第一次挂载渲染时被用来初始化状态,后续组件重渲染时,useState会直接返回当前存储的状态值,完全忽略传入的初始值参数。
组件首次渲染时,currentXMPID为初始值null,isAttachStorageOn()返回false,因此isAttachChecked初始化为false。
当后续currentXMPID更新触发重渲染时,isAttachStorageOn()返回true,因此第一个日志打印true,但此时useState已经完成初始化,会直接返回之前存储的false,所以第二个日志打印false。 - useEffect闭包与异步更新问题:你的
useEffect依赖数组为空,仅会在组件首次挂载后执行一次。且React的setState是批量异步更新的,在useEffect里调用setCurrentXMPID(xmpID)之后,当前闭包中的currentXMPID还是旧的初始值null,此时调用isAttachStorageOn()依然返回false,等于给isAttachChecked赋值了false,后续没有其他更新isAttachChecked的逻辑,自然状态不会变动。
修复方案
根据实际使用场景二选一即可:
- 若
isAttachChecked不需要用户手动修改,永远和isAttachStorageOn()的计算结果同步
直接删掉对应的useState定义,把它作为普通派生值即可,无需额外处理同步逻辑,频繁重渲染也能永远保持最新值:
// 删掉原有的 const [isAttachChecked, setAttachChecked] = useState(renderAttachState); const isAttachChecked = isAttachStorageOn();
- 若
isAttachChecked是可修改的状态,仅默认值从isAttachStorageOn()取
新增依赖currentXMPID的副作用,当currentXMPID变化时自动同步状态:
// 原有获取xmpID的useEffect不需要再调用setAttachChecked useEffect(() => { (async () => { const xmpID = await rpcClient.getXMPID(); setCurrentXMPID(xmpID); })(); }, []); // 新增同步副作用 useEffect(() => { setAttachChecked(isAttachStorageOn()); }, [currentXMPID]);
内容的提问来源于stack exchange,提问作者Dave Stein
相关产品推荐
相关产品推荐

