React父类组件与子函数组件模态框modal开关功能异常问题
问题核心原因
你遇到的所有异常都来自2个核心错误:
- 你将模态框子组件直接写在了
MenuItem组件内部,绝大多数UI组件库的下拉菜单类组件,在用户点击菜单项后会默认收起整个菜单,此时包括ChildComponent在内的所有菜单子元素会被直接卸载,你触发的状态变更自然无法在已经销毁的组件上生效。只有你重新打开菜单(也就是你描述的“临时关闭父组件再重新打开”),子组件重新挂载时才会读取到已经变更为true的showModal状态,渲染出模态框。 - 子组件额外维护了一套
modalOpen派生状态,属于完全不必要的冗余逻辑,增加了状态不同步的风险。
修复步骤
第一步:调整组件结构
将ChildComponent从MenuItem内部移到和菜单同级的位置,不要放在菜单的DOM结构内:
class Parent extends Component { constructor(props) { super(props); this.state = { showModal: false }; this.showModal = this.showModal.bind(this); this.closeModal = this.closeModal.bind(this); } showModal() { this.setState({ showModal: true }); } closeModal() { this.setState({ showModal: false }); } render() { return ( <> {/* 菜单结构 */} <MenuItem onClick={this.showModal}> 打开模态框 </MenuItem> {/* 模态框移到菜单外部 */} <ChildComponent prop1={prop1} isOpen={this.state.showModal} closeModal={this.closeModal} /> </> ) } }
第二步:简化子组件逻辑
删除子组件内冗余的本地状态,直接使用父组件传入的isOpen属性控制渲染即可:
const ChildComponent = ({ prop1, isOpen, closeModal }) => { console.log('isopen on child', isOpen) return ( <div> {isOpen && ( <button onClick={closeModal}> 点击关闭模态框 </button> )} </div> ) }
可选优化
如果你的UI库的MenuItem点击后会阻止事件冒泡或者有默认行为,可以在showModal方法里加上事件阻止逻辑:
showModal(e) { e.preventDefault(); e.stopPropagation(); this.setState({ showModal: true }); }
内容的提问来源于stack exchange,提问作者PatrickAllen
相关产品推荐
相关产品推荐

