React中父组件重渲染时useReducer状态内子组件未更新的问题
问题分析与解决方案
问题原因
你错误地把**React元素(组件执行后的JSX结果)**存在了useReducer的state中。当父组件因input状态变化重渲染时,useReducer的state仍为之前缓存的旧元素对象,不会自动重新执行组件函数生成新元素,导致renderBox3无法同步更新。
正确写法
useReducer应存储组件的标识(如字符串),而非直接存储JSX元素。在父组件的渲染逻辑中,根据标识动态执行对应组件函数生成最新JSX,即可响应state变化。
修改后的代码:
import React, { useReducer, useState } from 'react'; export default function TestReducerScreen() { console.log('App rerendered!'); const [input, setInput] = useState('Hi all'); const defaultBoxRender = () => { console.log('defaultboxRender render'); return <div id="defaultBoxRender"> <p>This is default BoxRender</p> <button onClick={() => dispatch("SHOW_ME_renderBox2")}>Change to renderBox2</button> </div> } const renderBox2 = () => { console.log('renderBox2 render'); return <div id='renderBox2'> <p>This is renderBox2</p> <button onClick={() => dispatch("SHOW_ME_renderBox3")}>Change to renderBox3</button> </div>; } const renderBox3 = () => { console.log('renderBox3 render'); return <div id='renderBox3'> <input type="text" onChange={(e) => setInput(e.target.value)} value={input} placeholder="typeing somethings...." /> <p>This is renderBox3 ; vl = {input}</p> <button onClick={() => setInput("Inside me")}>Change input values</button> <button onClick={() => dispatch("SHOW_ME_defaultBoxRender")}>Change to defaultBoxRender</button> </div>; } const reducer = (state, action) => { console.log('state = ', state); switch (action) { case 'SHOW_ME_defaultBoxRender': return 'default'; case 'SHOW_ME_renderBox2': return 'box2'; case 'SHOW_ME_renderBox3': return 'box3'; default: return state; } } // 初始状态存储组件标识,而非元素 const [currentBox, dispatch] = useReducer(reducer, 'default'); // 根据标识动态渲染对应组件 const renderCurrentBox = () => { switch(currentBox) { case 'default': return defaultBoxRender(); case 'box2': return renderBox2(); case 'box3': return renderBox3(); default: return defaultBoxRender(); } } return ( <div id='Container'> {renderCurrentBox()} </div> ); }
关键说明
- useReducer的state应存储可序列化的状态标识,而非React元素。React元素是对象,存储后会被缓存,无法随父组件重渲染自动更新。
- 父组件重渲染时,根据state中的标识重新执行组件函数,生成包含最新
input值的JSX,实现renderBox3的同步更新。
内容的提问来源于stack exchange,提问作者Phan Tấn Tài
相关产品推荐
相关产品推荐

