You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 05:15:38