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

如何在React函数中调用另一个组件?(以弹窗组件为例)

实现函数式调用Modal组件的两种方案

方案一:组件内状态控制(简单直接)

这种方法无需额外封装,在组件内通过状态控制Modal的显示/隐藏,逻辑清晰,适合单个组件场景使用:

修改ShareButton组件:

import { BiLink } from 'react-icons/bi';
import { useState } from 'react';
import NuggetModal from './NuggetModal';
import './ShareButton.css';

function ShareButton({postId}){
    const [isModalOpen, setIsModalOpen] = useState(false);

    function copyLinkOnClick() {
        const baseUrl = window.location.origin.toString();
        const urlToShare = baseUrl + '/post/' + postId;

        navigator.clipboard.writeText(urlToShare);
        // 调用状态更新打开Modal
        setIsModalOpen(true);
    }

    const closeModal = () => setIsModalOpen(false);

    return (
        <div className="share-button-container">
            <BiLink className="share-button" onClick={copyLinkOnClick}/>
            {/* 条件渲染Modal */}
            {isModalOpen && <NuggetModal textBody="链接已复制!" onClose={closeModal} />}
        </div>
    )
}

export default ShareButton;

给NuggetModal补充关闭逻辑:

import './NuggetModal.css';

function NuggetModal({textBody, onClose}) {
    return (
        <div className="nugget-container" onClick={onClose}>
            <div className="modal-content" onClick={(e) => e.stopPropagation()}>
                {textBody}
                <button onClick={onClose}>关闭</button>
            </div>
        </div>
    )
}

export default NuggetModal;

方案二:自定义Hook+React Portal(全局函数调用)

这种方案可以实现直接通过函数(如showModal('提示文本'))打开Modal,无需在使用组件中编写Modal标签,适合全局复用场景:

1. 封装全局Modal Hook

新建useModal.js文件:

import { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';
import NuggetModal from './NuggetModal';

// 全局挂载Modal的根节点,不存在则自动创建
let modalRoot = document.getElementById('modal-root');
if (!modalRoot) {
    modalRoot = document.createElement('div');
    modalRoot.id = 'modal-root';
    document.body.appendChild(modalRoot);
}

export function useModal() {
    const [modalState, setModalState] = useState({
        isOpen: false,
        textBody: ''
    });

    // 打开Modal的函数
    const showModal = (text) => {
        setModalState({
            isOpen: true,
            textBody: text
        });
    };

    // 关闭Modal的函数
    const closeModal = () => {
        setModalState({
            isOpen: false,
            textBody: ''
        });
    };

    // 通过Portal将Modal渲染到全局根节点
    useEffect(() => {
        if (modalState.isOpen) {
            const modalElement = <NuggetModal textBody={modalState.textBody} onClose={closeModal} />;
            ReactDOM.createPortal(modalElement, modalRoot);
        } else {
            ReactDOM.unmountComponentAtNode(modalRoot);
        }

        return () => ReactDOM.unmountComponentAtNode(modalRoot);
    }, [modalState]);

    return { showModal, closeModal };
}

2. 优化NuggetModal组件

import './NuggetModal.css';

function NuggetModal({textBody, onClose}) {
    return (
        <div className="nugget-container" onClick={onClose}>
            <div className="modal-content" onClick={(e) => e.stopPropagation()}>
                <p>{textBody}</p>
                <button className="close-btn" onClick={onClose}>×</button>
            </div>
        </div>
    )
}

export default NuggetModal;

3. 在ShareButton中使用

import { BiLink } from 'react-icons/bi';
import { useModal } from './useModal';
import './ShareButton.css';

function ShareButton({postId}){
    const { showModal } = useModal();

    function copyLinkOnClick() {
        const baseUrl = window.location.origin.toString();
        const urlToShare = baseUrl + '/post/' + postId;

        navigator.clipboard.writeText(urlToShare);
        // 直接调用函数打开Modal
        showModal('链接已复制到剪贴板!');
    }

    return (
        <div className="share-button-container">
            <BiLink className="share-button" onClick={copyLinkOnClick}/>
        </div>
    )
}

export default ShareButton;

内容的提问来源于stack exchange,提问作者Misu Kuma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 17:10:16