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

React已卸载组件状态更新报错:props传值到useState的解决方法

类组件传props给函数子组件触发内存泄漏警告问题解决

问题场景

类组件Viewer嵌套函数组件DragAndDrop并传递characters props:

class Viewer extends React.Component {
  // ... 其他逻辑代码
  render(){
    return(
      // ... 其他页面元素
      <DragAndDrop characters={characters}/>
    )
  }
}

子组件DragAndDrop中,能正常打印props.characters,但用其初始化useState时触发内存泄漏警告:

function DragAndDrop(props) {
  console.log("char",props.characters); // 可以正常输出内容
  const [characters, updateCharacters] = useState(props.characters); // 此处触发错误

  function handleOnDragEnd(result) {
    if (!result.destination) return;

    const items = Array.from(characters);
    const [reorderedItem] = items.splice(result.source.index, 1);
    items.splice(result.destination.index, 0, reorderedItem);

    updateCharacters(items);
  }

  // ... 组件渲染代码
}

错误信息

Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak. cancel all subscriptions an

解决方案

1. 改用useEffect同步props到state

直接用props.characters初始化useState会导致state与props不同步,且父组件重新渲染时可能触发不必要的state更新。通过useEffect监听props变化来同步state:

function DragAndDrop(props) {
  // 初始化state为默认空数组,避免直接依赖props
  const [characters, updateCharacters] = useState([]); 

  useEffect(() => {
    // 当props.characters变化时,更新子组件state
    updateCharacters(props.characters);
  }, [props.characters]); // 仅在props.characters引用变化时执行

  // ... 拖拽处理及渲染代码不变
}

2. 添加挂载状态标记,防止卸载后更新state

如果拖拽操作存在异步逻辑(比如延迟处理),组件卸载后仍执行updateCharacters会触发警告。添加useRef标记组件挂载状态:

function DragAndDrop(props) {
  const [characters, updateCharacters] = useState([]);
  const isMounted = useRef(true);

  useEffect(() => {
    updateCharacters(props.characters);
    // 组件卸载时将标记置为false
    return () => {
      isMounted.current = false;
    };
  }, [props.characters]);

  function handleOnDragEnd(result) {
    if (!result.destination) return;

    const items = Array.from(characters);
    const [reorderedItem] = items.splice(result.source.index, 1);
    items.splice(result.destination.index, 0, reorderedItem);

    // 仅当组件处于挂载状态时更新state
    if (isMounted.current) {
      updateCharacters(items);
    }
  }

  // ... 渲染代码
}

3. 确保父组件传递的props引用稳定

如果父组件Viewer每次渲染都生成新的characters数组,会导致子组件useEffect频繁触发。在父组件中优化characters的引用稳定性:

  • 类组件可继承React.PureComponent,或在shouldComponentUpdate中判断characters是否真的变化
  • 若characters是动态生成的,可在父组件中缓存其引用,避免不必要的更新
// 示例:Viewer类组件改用PureComponent优化
class Viewer extends React.PureComponent {
  // ... 其他代码
  render(){
    const stableCharacters = this.state.characters;
    return(
      <DragAndDrop characters={stableCharacters}/>
    )
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 22:45:37