React自定义Modal组件重复使用时CSS类切换仅对最后一个实例生效问题
自定义Modal多实例CSS类切换失效问题解决方案
问题根因
你的实现存在两个核心问题:
- 父组件每次更新状态时,三个Modal实例都会触发重渲染,各自执行
componentDidUpdate生命周期 - 原始的
componentDidUpdate未判断当前组件的modalOpen属性是否真的发生变化,只要组件更新就会执行body类名的增删逻辑,后执行的实例逻辑会覆盖前面的操作,因此只有最后渲染的第三个Modal的操作会生效
解决方案1:使用React.PureComponent优化
将Modal组件的继承对象从React.Component改为React.PureComponent,PureComponent会自动对props做浅比较,只有当前组件的props发生变化时才会触发重渲染和生命周期执行,避免无关实例的逻辑被执行。
// 修改前 export default class Modal extends React.Component { // 修改后 export default class Modal extends React.PureComponent {
解决方案2:在componentDidUpdate中手动判断props变化
无需修改继承对象,只要给Modal组件加上props变化判断逻辑即可:
import React from "react"; export default class Modal extends React.Component { constructor(props) { super(props); this.state = { modalOpen: false }; } componentDidUpdate(prevProps) { // 只有modalOpen属性发生变化时才执行类名切换逻辑 if (prevProps.modalOpen === this.props.modalOpen) return; if (this.props.modalOpen) { console.log("Open!", this.props.modalOpen); document.body.classList.add("drawer-open"); } else { console.log("Closed!", this.props.modalOpen); document.body.classList.remove("drawer-open"); } } render() { return ( <div className="mymodal" id={this.props.modalName}> <div onClick={this.props.toggleModal} className={`mymodal-overlay ${this.props.modalOpen && "active"}`} ></div> <div className={`mymodal-content d-flex flex-column ${ this.props.modalOpen && "active" }`} > <header className="p-2 border-bottom d-flex"> <span className="material-icons clickable" onClick={this.props.toggleModal} > close </span> <div className="flex-grow-1 ml-2">{this.props.modalTitle}</div> </header> <div className="p-2 flex-grow-1">{this.props.modalBody}</div> <footer className="p-2 border-top">© ChidoPrime 2021</footer> </div> </div> ); } }
补充优化:如果你的业务场景允许同时打开多个Modal,建议将body类名的切换逻辑改为计数器实现:打开一个Modal计数器+1,关闭一个-1,计数器为0时才移除
drawer-open类,避免多个Modal交叉操作时类名被误删。
内容的提问来源于stack exchange,提问作者iChido
相关产品推荐
相关产品推荐

