为何修改updateTrigger无法触发EditorBasic的componentDidUpdate?
问题原因与解决方案
1. componentDidUpdate未触发的核心原因
当你点击"Click to toggle EditorBasic"时,组件的生命周期逻辑是:
- 首次点击:
showEditorBasic从false变为true,EditorBasic是首次挂载,只会执行componentDidMount,不会触发componentDidUpdate - 第二次点击:
showEditorBasic变为false,组件被完全卸载 - 后续点击:每次都是重新挂载/卸载组件,永远不会进入更新生命周期
updateTrigger的变化只有在组件已挂载的前提下才会触发componentDidUpdate,但你的逻辑通过showEditorBasic控制组件的挂载与卸载,导致这个prop的变化永远无法被组件的更新钩子捕获。
2. 组件高度获取的误区
你的aRef指向的是包裹EditorBasic的外层<div>,而非EditorBasic组件内部的元素。如果要获取组件自身的高度,需要直接给组件内部的根元素添加ref。
修复后的代码示例
App.tsx 修改
import * as React from 'react'; import EditorBasic from './EditorBasic'; interface IAppProps {} interface IAppState { showEditorBasic: boolean; updateTrigger: number; } export default class App extends React.Component<IAppProps, IAppState> { aRef: React.RefObject<HTMLDivElement>; editorRef: React.RefObject<EditorBasic>; constructor(props) { super(props); this.state = { showEditorBasic: false, updateTrigger: 0, }; this.aRef = React.createRef(); this.editorRef = React.createRef(); } calculateNextHeight = () => { console.log('外层包裹div高度', this.aRef.current?.clientHeight); // 调用EditorBasic暴露的方法获取内部高度 console.log('EditorBasic内部高度', this.editorRef.current?.getInnerHeight()); }; toggleEditor = () => { this.setState(prev => ({ showEditorBasic: !prev.showEditorBasic, updateTrigger: prev.updateTrigger + 1, }), () => { // 组件挂载完成后主动触发高度计算 if (this.state.showEditorBasic) { this.calculateNextHeight(); } }); }; render() { return ( <div> <div onClick={this.toggleEditor}> Click to toggle EditorBasic </div> {this.state.showEditorBasic && ( <div ref={this.aRef}> <EditorBasic ref={this.editorRef} calculateNextHeight={this.calculateNextHeight} updateTrigger={this.state.updateTrigger} /> </div> )} </div> ); } }
EditorBasic.tsx 修改
import * as React from 'react'; interface IEditorBasicProps { calculateNextHeight: () => void; updateTrigger: number; } interface IEditorBasicState {} export default class EditorBasic extends React.Component< IEditorBasicProps, IEditorBasicState > { innerRef: React.RefObject<HTMLDivElement>; constructor(props) { super(props); this.innerRef = React.createRef(); } handleResize = () => { this.props.calculateNextHeight(); }; // 暴露给父组件获取内部高度的方法 getInnerHeight = () => { return this.innerRef.current?.clientHeight; }; componentDidMount() { window.addEventListener('resize', this.handleResize); // 挂载完成后立即计算一次高度 this.handleResize(); } componentDidUpdate(prevProps) { if (this.props.updateTrigger !== prevProps.updateTrigger) { this.handleResize(); } } componentWillUnmount() { // 移除监听避免内存泄漏 window.removeEventListener('resize', this.handleResize); } render() { return ( <div ref={this.innerRef}> <br /> <br /> EditorBasic {this.props.updateTrigger} <br /> <br /> </div> ); } }
关键修复点
- 给
EditorBasic内部根元素添加ref,确保获取的是组件自身的高度 - 在父组件
setState的回调中,组件挂载完成后主动触发高度计算 - 新增
componentWillUnmount移除resize监听,避免内存泄漏 - 如果需要通过
updateTrigger触发组件更新,需保证组件始终处于挂载状态(比如用CSS隐藏替代卸载)
内容的提问来源于stack exchange,提问作者SoftTimur
相关产品推荐
相关产品推荐

