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
相关产品推荐
相关产品推荐

