props、Context、useReducer、外部 store 怎么选?
先理解原理和示例,再练习完整口述与追问。
回答要点
局部状态靠近使用者;兄弟共享可提升状态,跨层依赖可用 Context;复杂状态转移可用 reducer。跨页面复杂状态再按项目选外部 store。Context 是传播机制,不自动提供细粒度订阅和持久化。
原理拆解
状态选择先看所有者与订阅粒度。父子少量共享用提升状态和 props;某个子树需要共同依赖可用 Context;状态转换复杂可用 useReducer 显式描述 action;跨页面、需选择器与外部订阅的状态可采用合适 store。Context 是传递依赖的方式,不自带细粒度选择器或持久化能力。
示例与推演
主题 Context 更新可让消费者获取新主题;高频变化的大表格全部塞入一个 Context 可能扩大更新范围,可拆作用域或使用选择器式外部状态。Reducer 里定义 add/remove/reset 等纯转换,网络请求留在事件、Effect 或专门服务中,完成后再 dispatch 结果。
易错点
不要把“全局”当成更好复用。Reducer 不能原地修改旧对象,Context value 每次新对象也可能制造无关更新,SSR 外部 store 仍需按请求隔离。
参考回答可直接练习口述
我先把状态放在最近需要它的组件,需要兄弟共享就提升到共同父级,跨多层的稳定依赖再用 Context。复杂状态转移可用 useReducer 保证逻辑集中和可预测。跨页面状态按现有项目选 store,服务端数据缓存和 UI 状态分开设计。Context 只是传播能力,不自动解决缓存、持久化或细粒度订阅。
面试官可能继续问追问与完整解答展开收起
追问
Provider 的 value 每次创建新对象有何影响?reducer 为什么应保持纯净?服务端数据缓存与 UI 状态是否应该混在一起?
追问回答
Provider value 每次新建引用可能使消费者更新,先考虑拆 Context 和稳定必要值。reducer 应纯净,因为它负责把旧状态和 action 映射到新状态,不负责请求。服务器数据有失效、重取、去重等生命周期,与弹窗开关和草稿不同,不应只当普通全局变量堆在一起。