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

如何将非Redux的React表单改造为Redux方案以避免冗余渲染?

用Redux Toolkit解决表单组件不必要渲染问题

问题根源

你当前的实现中,BigForm作为父组件维护dataA和dataB两个状态,每次更新其中一个状态时,父组件会重新渲染,导致两个子组件FormA和FormB也跟着重新渲染——即使另一个组件的props并没有变化。Redux可以让子组件直接订阅自己需要的状态,避免这种无意义的渲染。

解决方案步骤(基于Redux Toolkit,官方推荐的现代Redux用法)

1. 安装依赖

首先安装Redux Toolkit和React-Redux:

npm install @reduxjs/toolkit react-redux

2. 创建表单状态Slice

在项目中新建features/form/formSlice.js文件,定义状态和操作:

import { createSlice } from '@reduxjs/toolkit';

const initialState = {
  dataA: '',
  dataB: ''
};

const formSlice = createSlice({
  name: 'form',
  initialState,
  reducers: {
    updateDataA: (state, action) => {
      state.dataA = action.payload;
    },
    updateDataB: (state, action) => {
      state.dataB = action.payload;
    }
  }
});

export const { updateDataA, updateDataB } = formSlice.actions;
export default formSlice.reducer;

3. 配置Redux Store

新建app/store.js文件:

import { configureStore } from '@reduxjs/toolkit';
import formReducer from '../features/form/formSlice';

export const store = configureStore({
  reducer: {
    form: formReducer
  }
});

4. 在根组件中包裹Provider

修改你的根组件(比如index.js),用Redux的Provider包裹整个应用:

import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import { store } from './app/store';
import { BigForm } from './BigForm';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Provider store={store}>
    <BigForm />
  </Provider>
);

5. 修改组件代码

更新FormA、FormB和BigForm,让它们直接和Redux交互:

import React, { useEffect } from "react";
import { useSelector, useDispatch } from 'react-redux';
import { updateDataA } from './features/form/formSlice';

const FormA = () => {
  useEffect(()=>{ console.log('Form A was just rendered')})
  // 只订阅dataA状态
  const dataA = useSelector(state => state.form.dataA);
  const dispatch = useDispatch();

  return (
    <div>
      <input onChange={(e) => dispatch(updateDataA(e.target.value))}></input>
      <p>Input Form A{dataA}</p>
    </div>
  );
};

const FormB = () => {
  useEffect(()=>{ console.log('Form B was just rendered')})
  // 只订阅dataB状态
  const dataB = useSelector(state => state.form.dataB);
  const dispatch = useDispatch();

  return (
    <div>
      <input onChange={(e) => dispatch(updateDataB(e.target.value))}></input>
      <p>Input Form B{dataB}</p>
    </div>
  );
};

export function BigForm () {
  // 父组件不再维护状态,只负责渲染子组件
  return (
    <div className="App">
      <FormA />
      <FormB />
    </div>
  );
}

效果验证

现在在FormA输入内容时,只有FormA会触发渲染日志;在FormB输入时,只有FormB会触发渲染日志,彻底解决了不必要的渲染问题。同时所有表单数据都统一存储在Redux store中,方便后续聚合使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 16:54:26