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

如何避免React组件因多状态更新重复重渲染?是否为不良模式?

React组件两次重渲染问题的解决方法

问题分析

你的<App />组件通过点击事件先更新第一个状态,再通过useEffect()监听该状态变化来更新第二个状态,这种写法会触发两次组件重渲染——第一次是第一个状态更新时,第二次是第二个状态更新时。在存在大量props传递的项目中,多次重渲染会引发明显卡顿。

解决方案

1. 合并状态更新逻辑,避免中间状态触发渲染

如果第一个状态只是计算第二个状态的中间值,完全可以在交互事件中直接计算最终结果,只更新目标状态:

import { useState } from "react";

function App() {
  const [total, setTotal] = useState(0);

  const handleClick = () => {
    // 直接计算最终的total值,一次更新
    setTotal(prev => prev + 2);
  };

  console.log("组件重渲染");
  return (
    <div>
      <button onClick={handleClick}>点击</button>
      <p>Total: {total}</p>
    </div>
  );
}

如果确实需要保留两个状态的关联逻辑,可以将它们合并为一个状态对象,通过一次状态更新完成:

import { useState } from "react";

function App() {
  const [data, setData] = useState({ count: 0, total: 0 });

  const handleClick = () => {
    setData(prev => {
      const newCount = prev.count + 1;
      return {
        count: newCount,
        total: newCount * 2
      };
    });
  };

  console.log("组件重渲染");
  return (
    <div>
      <button onClick={handleClick}>点击</button>
      <p>Count: {data.count}</p>
      <p>Total: {data.total}</p>
    </div>
  );
}

2. 使用useReducer统一管理状态更新

当状态逻辑复杂时,用useReducer将状态更新逻辑集中处理,一次dispatch就能完成关联状态的更新,React会自动合并状态更新,只触发一次重渲染:

import { useReducer } from "react";

const initialState = { count: 0, total: 0 };

function reducer(state, action) {
  switch (action.type) {
    case "INCREMENT":
      const newCount = state.count + 1;
      return {
        count: newCount,
        total: newCount * 2
      };
    default:
      return state;
  }
}

function App() {
  const [state, dispatch] = useReducer(reducer, initialState);

  const handleClick = () => {
    dispatch({ type: "INCREMENT" });
  };

  console.log("组件重渲染");
  return (
    <div>
      <button onClick={handleClick}>点击</button>
      <p>Count: {state.count}</p>
      <p>Total: {state.total}</p>
    </div>
  );
}

3. 用useRef存储中间变量(仅当中间值不需要触发渲染时)

如果第一个状态只是用于计算,不需要在UI中展示,可以用useRef存储,避免因状态更新触发渲染:

import { useState, useRef } from "react";

function App() {
  const countRef = useRef(0);
  const [total, setTotal] = useState(0);

  const handleClick = () => {
    countRef.current += 1;
    setTotal(countRef.current * 2);
  };

  console.log("组件重渲染");
  return (
    <div>
      <button onClick={handleClick}>点击</button>
      <p>Total: {total}</p>
    </div>
  );
}

是否属于React不良模式

你之前用useEffect监听状态来更新另一个状态的写法,属于React的不良模式。这种写法会触发额外的重渲染,不仅降低性能,还会让状态依赖逻辑变得隐晦,增加维护成本。React官方建议尽量在状态更新的源头处理关联逻辑,避免通过useEffect触发二次状态更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 04:35:22