如何在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
相关产品推荐
相关产品推荐

