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

React中父组件状态变更时如何避免子组件重渲染?

问题:父组件控制子组件显隐时保留子组件状态(不使用状态管理)

你当前遇到的核心问题不是重渲染,而是当父组件中{open && <MyComponentMemoized />}为false时,子组件会被完全卸载——再次显示时会创建全新的组件实例,内部状态自然会重置。React.memo只能阻止组件在props不变时的重渲染,无法解决卸载/重新挂载导致的状态丢失问题。

下面是两种无需状态管理的解决方案:


方案1:用CSS控制显示隐藏(不卸载组件)

通过CSS的display属性控制子组件的显示与隐藏,让组件始终存在于DOM中,避免卸载导致的状态丢失。

修改App.js

import "./styles.css";
import React, { useState, useCallback } from "react";
import MyComponent from "./components/MyComponent";

export default function App() {
  const [open, setOpen] = useState(false);

  const handleClick = useCallback(() => {
    setOpen((prevOpen) => !prevOpen);
  }, []);

  return (
    <div className="App">
      <button onClick={handleClick}>{open ? "Close div" : "Open div"}</button>
      {/* 用style控制显示,不卸载组件 */}
      <MyComponent style={{ display: open ? "block" : "none" }} />
    </div>
  );
}

可选:调整MyComponent接收样式

// MyComponent.js
import React, { memo } from "react";

const MyComponent = ({ style }) => {
  const [showText1, setShowText1] = useState(false);
  const [showText2, setShowText2] = useState(false);
  const [showText3, setShowText3] = useState(false);

  const handleShowText1 = () => setShowText1(!showText1);
  const handleShowText2 = () => setShowText2(!showText2);
  const handleShowText3 = () => setShowText3(!showText3);

  return (
    <div style={style}>
      Hello there
      <button onClick={handleShowText1}>Show text 1</button>
      {showText1 && <div>Text 1!</div>}
      <button onClick={handleShowText2}>Show text 2</button>
      {showText2 && <div>Text 2!</div>}
      <button onClick={handleShowText3}>Show text 3</button>
      {showText3 && <div>Text 3!</div>}
    </div>
  );
};

export default memo(MyComponent);

方案2:将子组件状态提升到父组件

如果不想让子组件始终存在于DOM,可以把它的内部状态移到父组件中保存,通过props传递给子组件,这样即使子组件卸载,状态也会保留在父组件中,再次挂载时可以恢复。

修改App.js

import "./styles.css";
import React, { useState, useCallback } from "react";
import MyComponent from "./components/MyComponent";

export default function App() {
  const [open, setOpen] = useState(false);
  // 保存子组件的状态
  const [textStates, setTextStates] = useState({
    showText1: false,
    showText2: false,
    showText3: false
  });

  const handleClick = useCallback(() => {
    setOpen((prevOpen) => !prevOpen);
  }, []);

  // 统一处理子组件的状态切换
  const handleTextToggle = (key) => {
    setTextStates(prev => ({
      ...prev,
      [key]: !prev[key]
    }));
  };

  return (
    <div className="App">
      <button onClick={handleClick}>{open ? "Close div" : "Open div"}</button>
      {open && (
        <MyComponent
          textStates={textStates}
          onTextToggle={handleTextToggle}
        />
      )}
    </div>
  );
}

修改MyComponent.js

import React, { memo } from "react";

const MyComponent = ({ textStates, onTextToggle }) => {
  return (
    <div>
      Hello there
      <button onClick={() => onTextToggle("showText1")}>Show text 1</button>
      {textStates.showText1 && <div>Text 1!</div>}
      <button onClick={() => onTextToggle("showText2")}>Show text 2</button>
      {textStates.showText2 && <div>Text 2!</div>}
      <button onClick={() => onTextToggle("showText3")}>Show text 3</button>
      {textStates.showText3 && <div>Text 3!</div>}
    </div>
  );
};

export default memo(MyComponent);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 01:05:01