react-modal 异常问题排查:多模态框内容显示错误
解决React Modal复用多个实例时内容固定显示最后一个值的问题
嘿,我明白你遇到的麻烦了——点击第一个按钮打开模态框,结果显示的却是第二个的hint值"banana",对吧?这个问题的核心原因很简单:你所有的HintModal实例都共享了App组件里的同一个modalIsOpen状态和hint值。
当你点击第一个按钮时,App的state会把modalIsOpen设为true,同时hint设为"mango"。但此时两个HintModal里的Modal组件都会因为isOpen={this.state.modalIsOpen}而处于激活状态,而React在渲染多个相同组件时,会复用DOM元素,最后渲染的那个Modal(也就是第二个,hint为"banana"的)就会覆盖掉第一个的内容,所以你看到的永远是最后一个的hint。
下面给你两种解决方案,按需选择:
方案一:让每个模态框独立管理自己的状态
这是最简单的解决方式,把状态从父组件App下移到HintModal内部,让每个模态框自己控制是否打开,这样它们之间就不会互相干扰了。
修改你的hintModal.jsx:
import React, { useState } from 'react'; import Modal from 'react-modal'; const HintModal = ({ hint }) => { // 每个模态框自己维护打开状态 const [modalIsOpen, setModalIsOpen] = useState(false); const openModal = () => { setModalIsOpen(true); }; const closeModal = () => { setModalIsOpen(false); }; return ( <React.Fragment> <button onClick={openModal}>Open Modal</button> <Modal isOpen={modalIsOpen} onRequestClose={closeModal} contentLabel="Hint Modal" > <h2>Hint</h2> <p>{hint}</p> <button onClick={closeModal}>Close</button> </Modal> <p>We should see: {hint}</p> </React.Fragment> ); }; export default HintModal;
然后简化App.js,去掉共享的state:
import React, { Component } from 'react'; import HintModal from './hintModal'; import Modal from 'react-modal'; import './App.css'; Modal.setAppElement('#root'); class App extends Component { render() { return ( <React.Fragment> <h1>Modal Test</h1> <h2>First Modal</h2> <HintModal hint="mango" /> <hr /> <h2>Second Modal</h2> <HintModal hint="banana" /> </React.Fragment> ); } } export default App;
方案二:在父组件统一管理多个模态框的状态
如果你需要在父组件里统一控制所有模态框(比如做一个全局关闭按钮),可以给每个模态框分配唯一标识,用对象来管理每个模态框的打开状态:
修改App.js的状态和方法:
import React, { Component } from 'react'; import HintModal from './hintModal'; import Modal from 'react-modal'; import './App.css'; Modal.setAppElement('#root'); class App extends Component { // 用对象存储每个模态框的打开状态,键是唯一标识 state = { modals: { mangoModal: false, bananaModal: false } }; openModal = (modalKey) => { this.setState(prevState => ({ modals: { ...prevState.modals, [modalKey]: true } })); }; closeModal = (modalKey) => { this.setState(prevState => ({ modals: { ...prevState.modals, [modalKey]: false } })); }; render() { return ( <React.Fragment> <h1>Modal Test</h1> <h2>First Modal</h2> <HintModal modalIsOpen={this.state.modals.mangoModal} openModal={() => this.openModal('mangoModal')} closeModal={() => this.closeModal('mangoModal')} hint="mango" /> <hr /> <h2>Second Modal</h2> <HintModal modalIsOpen={this.state.modals.bananaModal} openModal={() => this.openModal('bananaModal')} closeModal={() => this.closeModal('bananaModal')} hint="banana" /> </React.Fragment> ); } } export default App;
hintModal.jsx保持你原来的代码即可,不需要修改。
这样每个模态框的打开状态都是独立的,点击第一个按钮只会打开对应hint的模态框,不会出现内容被覆盖的问题了。
内容的提问来源于stack exchange,提问作者anaximander
相关产品推荐
相关产品推荐

