You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 21:36:02