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

React中如何避免useReducer重复渲染?状态未合并问题求助

React useReducer 状态合并与冗余渲染问题解决

问题分析

  • 每个InputType组件单独实例化useReducer,导致两个组件维护完全独立的状态,自然无法得到合并后的{name: "MIKE", surname: "JORDAN"}——各自的state从INITIAL_STATE初始化,只会更新自身负责的字段。
  • 将useReducer移到父组件Office后,状态统一了,但父组件会因state变化触发重新渲染,连带导致两个InputType出现冗余渲染。

解决方案

  1. 统一状态管理:把useReducer放在父组件Office中,维护全局表单状态,避免子组件各自为政。
  2. 改造受控组件:InputType改为受控组件,接收父组件传递的value和onChange回调,不再自行维护状态。
  3. 削减冗余渲染:用React.memo包裹InputType,仅当传入的props发生变化时才重新渲染。

修改后的代码

officeReducer(保持不变)

export const INITIAL_STATE = {
    name: "",
    surname: "",
};

const ACTIONS = {
    CHANGE_INPUT: "CHANGE_INPUT",
}

export const officeReducer = (state, action) => {
    switch (action.type) {
      case ACTIONS.CHANGE_INPUT:
          return {
              ...state,
              [action.payload.name]: action.payload.value
          }
      default: {
          return state
      }
  }
}

InputType.js

import React from "react";

// 用React.memo包裹,减少无意义的重新渲染
export const InputType = React.memo((props) => {
    const { value, onChange, id, type, required, name, placeholder } = props;

    return (
      <div className={styles.inputBox}>
        <input 
          id={id} 
          type={type} 
          required={required} 
          name={name} 
          value={value}
          onChange={onChange}
        />
        <label 
          htmlFor={id} 
          className={value ? styles.inputFilled : ""}
        >
          {placeholder}
        </label>
      </div>
    )
})

Office.js

import { useReducer } from "react";
import { InputType } from "./InputType";
import { officeReducer, INITIAL_STATE } from "../../functions/officeReducer";

const Office = () => {
  const [state, dispatch] = useReducer(officeReducer, INITIAL_STATE);

  const handleChange = (e) => {
    dispatch({ 
      type: "CHANGE_INPUT", 
      payload: { name: e.target.name, value: e.target.value }
    });
  };

  return (
    <div className={styles.dataBox}>
      <div className={styles.dataInputs}>
        <InputType 
          placeholder={'Surname'} 
          name={'surname'} 
          required={true} 
          type={'text'}
          value={state.surname}
          onChange={handleChange}
        />
        <InputType 
          placeholder={'Name'} 
          name={'name'} 
          required={true} 
          type={'text'}
          value={state.name}
          onChange={handleChange}
        />
      </div>
    </div>
  )
}

额外说明

  • 移除了InputType中多余的useState,直接用传入的value判断是否添加inputFilled样式,逻辑更统一。
  • React.memo会对InputType的props做浅比较,只有当value或onChange变化时才触发渲染,避免父组件state更新时的冗余渲染。

内容的提问来源于stack exchange,提问作者Gleymas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 17:10:39