React按角色渲染的两个子组件更新状态时另一组件未同步原因
问题产生的根本原因
你当前的写法是互斥条件渲染,同一时间React组件树里只会存在Demo1、Demo2中的一个组件,不存在两个子组件同时挂载、同时接收props的场景,自然不会出现你预期的"一个组件更新状态,另一个同步拿到新值"的效果。
- 你写的三元判断
user.role === "user" ? <Demo1 /> : <Demo2 />是二选一的渲染逻辑:当用户角色匹配user时,React只会创建并挂载Demo1的组件实例,Demo2完全不会被渲染,不在当前组件树中;反之则只会挂载Demo2,Demo1不存在。 - 你观察到的"初始加载时两个子组件接收到的状态值完全一致",本质是你分别切换角色、单独加载两个组件时,两个组件各自首次挂载拿到的初始
staVal都是"hi",但两个组件从来没有在同一次页面渲染中同时存在过。 - 当你在Demo1内点击按钮触发状态更新时,父组件重渲染后依然会走一遍角色判断逻辑,只要角色还是user,重渲染的就只有Demo1组件,Demo2根本没有被挂载,没有接收props的载体,自然谈不上状态同步。
验证方式
你可以给两个子组件都加上挂载/卸载的日志,就能直观看到这个渲染逻辑:
在Demo1、Demo2中都加入如下代码:
import { useEffect } from "react"; // 组件内加入 useEffect(() => { console.log("当前组件挂载"); return () => console.log("当前组件卸载"); }, []);
修改localStorage里的auth值切换角色后刷新页面,你会发现控制台永远只会打印其中一个组件的挂载日志,不会两个组件同时挂载。
对应场景的修复方案
如果你的业务需求是两个组件都需要保留内部状态、同时接收父组件的最新值,只是根据用户角色控制展示/隐藏,不要用三元运算符做互斥渲染,改成两个组件都常驻组件树,通过CSS的display属性控制显隐即可:
// 父组件return部分修改为 return ( <div> <div style={{ display: user.role === "user" ? "block" : "none" }}> <Demo1 staVal={staVal} handler={() => setStaVal("google")} /> </div> <div style={{ display: user.role === "user" ? "none" : "block" }}> <Demo2 staVal={staVal} /> </div> </div> );
这种写法下两个组件会同时挂载在组件树中,父组件的staVal更新时,两个组件都会同步接收到最新的props值。
内容的提问来源于stack exchange,提问作者All in All
相关产品推荐
相关产品推荐

