React+Redux开发多内容模态框无法分别打开问题求解
问题根因
你当前的Redux全局只存储了一个布尔类型的isModalOpen状态,所有Modal组件都读取同一个状态值,只要状态为true,页面内所有Modal会同时渲染,无法区分不同模态框的开关状态,这就是第二个模态框功能失效的原因。
修改方案
我们把Redux存储的模态框状态从布尔值改为当前激活的模态框唯一标识,通过id匹配控制对应模态框的展示:
1. 修改Redux相关逻辑(action和reducer)
首先调整action的传参,以及reducer的存储结构:
action/index.js
// 原来的isModalOpen action修改为接收模态框id,传null代表关闭所有模态框 export const setActiveModal = (modalId) => { return { type: 'SET_ACTIVE_MODAL', payload: modalId } }
reducer/index.js
const initialState = { activeModal: null // 初始值为null,代表没有模态框打开 } const rootReducer = (state = initialState, action) => { switch(action.type) { case 'SET_ACTIVE_MODAL': return { ...state, activeModal: action.payload } default: return state } } export default rootReducer
2. 修改Modal.js组件
给组件新增modalId属性,只有Redux中存储的激活id和当前组件id匹配时才渲染,同时补充阻止事件冒泡逻辑,避免点击模态框内容时误触发关闭:
import React from 'react'; import './Modal.css'; import {useSelector, useDispatch} from 'react-redux'; import { setActiveModal } from '../actions/index'; // 组件接收modalId作为必填参数 const Modal = (props) => { const dispatch = useDispatch(); const activeModal = useSelector(state => state.activeModal); const closeModal = () => { dispatch(setActiveModal(null)); } // 只有当前激活id和组件id匹配时才渲染 if(activeModal !== props.modalId) return null; return( <div id="modal-container" onClick={closeModal}> <div id="modal" onClick={(e) => e.stopPropagation()}> <span onClick={closeModal}>Close</span> <h2>Modal</h2> <p>description</p> {props.children} </div> </div> ); } export default Modal;
3. 修改App.js
给两个Modal分别传入唯一id,打开模态框时dispatch对应id即可:
import React from 'react'; import { useDispatch} from 'react-redux'; import Modal from './Modals/Modal'; import Contents1 from './Modals/Contents1'; import Contents2 from './Modals/Contents2'; import { setActiveModal } from './actions/index'; import './App.css'; const App = () => { const dispatch = useDispatch(); const openModal1 = () => { dispatch(setActiveModal('modal1')); }; const openModal2 = () => { dispatch(setActiveModal('modal2')); }; return ( <div> <button onClick={openModal1}>Open Modal 1</button> <Modal modalId="modal1"> <Contents1 /> </Modal> <button onClick={openModal2}>Open Modal 2</button> <Modal modalId="modal2"> <Contents2 /> </Modal> </div> ); } export default App;
后续如果要新增更多模态框,只需要给新Modal设置唯一id,打开时dispatch对应id即可,扩展性更强。
内容的提问来源于stack exchange,提问作者Azu
相关产品推荐
相关产品推荐

