React JS实现动态模态框:无法二次打开及首次无数据问题求解
问题根因
1. 模态框仅能打开一次
你在子组件内部单独维护了openModal显隐状态,点击关闭按钮时仅修改了子组件内部的状态,父组件的portfolio.show值始终为true。后续再次点击View Project按钮时,父组件传递给子组件的show值没有变化,useEffect监听不到更新,就不会重新将子组件的openModal设为true,导致模态框无法弹出。
2. 首次打开模态框数据加载失败
父组件传递给子组件的portfolioData是结构为{data: 项目详情, show: 布尔值}的对象,你直接将portfolioData赋值给portfolioItem后取image、title等字段,实际这些字段都存在portfolioData.data下,所以读取不到对应值。
修复方案
推荐将模态框的显隐状态统一交由父组件维护,避免父子组件状态不同步,修改后的代码如下:
父组件修改后代码
import React, { useState } from 'react'; import '../assets/css/portfolio.scss'; import PortfolioModal from '../components/PortfolioModal'; import portfolioItems from '../data/portfolio'; const PortfolioScreen = () => { const [portfolio, setportfolio] = useState({ data: null, show: false }); const openModal = (portfolioItem) => { setportfolio({ data: portfolioItem, show: true, }); }; // 新增关闭模态框方法 const closeModal = () => { setportfolio(prev => ({ ...prev, show: false })) } return ( <> <section className='portfolio-section sec-padding'> <div className='container'> <div className='row'> <div className='section-title'> <h2>Recent Work</h2> </div> </div> <div className='row'> {portfolioItems.map((portfolioItem) => ( <div className='portfolio-item' key={portfolioItem._id}> <div className='portfolio-item-thumbnail'> <img src={portfolioItem.image} alt='portfolio item thumb' /> <h3 className='portfolio-item-title'> {portfolioItem.title} </h3> <button onClick={() => openModal(portfolioItem)} type='button' className='btn view-project-btn'> View Project </button> </div> </div> ))} {/* 传递关闭方法,直接传项目数据 */} <PortfolioModal portfolioData={portfolio.data} show={portfolio.show} onClose={closeModal} /> </div> </div> </section> </> ); }; export default PortfolioScreen;
子组件修改后代码
import React from 'react'; import { NavLink } from 'react-router-dom'; // 移除内部冗余的状态和useEffect,直接使用props控制 const PortfolioModal = ({ portfolioData, show, onClose }) => { // 项目数据为空时不渲染内容避免报错 if(!portfolioData) return null return ( <> <div className={`portfolio-popup ${show ? 'open' : ''}`}> <div className='pp-inner'> <div className='pp-content'> <div className='pp-header'> <button className='btn pp-close' onClick={onClose} > <i className='fas fa-times pp-close'></i> </button> <div className='pp-thumbnail'> <img src={portfolioData.image} alt={`${portfolioData.title}`} /> </div> <h3 className='portfolio-item-title'>{portfolioData.title}</h3> </div> <div className='pp-body'> <div className='portfolio-item-details'> <div className='description'> <p>{portfolioData.description}</p> </div> <div className='general-info'> <ul> <li> Created - <span>{portfolioData.creatDate}</span> </li> <li> Technology Used - <span>{portfolioData.technologyUsed}</span> </li> <li> Role - <span>{portfolioData.Role}</span> </li> <li> View Live - <span> <NavLink to='#' target='_blank'> {portfolioData.domain} </NavLink> </span> </li> </ul> </div> </div> </div> </div> </div> </div> </> ); }; export default PortfolioModal;
内容的提问来源于stack exchange,提问作者John Zampa
相关产品推荐
相关产品推荐

