我对React中模态的概念有一个问题。当使用jQuery服务器端呈现的模板时,我习惯于有一个空的全局模态模板始终可用(包括在始终扩展的基础模板中)。然后当进行 AJAX 调用时,我只是填充了模态..类似于以下内容:
$('.modal-global-content').html(content); $('.modal-global').show();
那么我该如何在React中实现这个概念呢?
pkwftd7m1#
有几种方法可以做到这一点。第一种方法涉及从父组件传入模态状态。下面是如何做到这一点-首先是父App.js组件:
App.js
// App.js import React from "react"; import Modal from "./Modal"; const App = () => { const [showModal, updateShowModal] = React.useState(false); const toggleModal = () => updateShowModal(state => !state); return ( <div> <h1>Not a modal</h1> <button onClick={toggleModal}>Show Modal</button> <Modal canShow={showModal} updateModalState={toggleModal} /> </div> ); } export default App;
下面是Modal.js子组件,它将呈现模态:
Modal.js
// Modal.js import React from "react"; const modalStyles = { position: "fixed", top: 0, left: 0, width: "100vw", height: "100vh", background: "blue" }; const Modal = ({ canShow, updateModalState }) => { if (canShow) { return ( <div style={modalStyles}> <h1>I'm a Modal!</h1> <button onClick={updateModalState}>Hide Me</button> </div> ); } return null; }; export default Modal;
这种方法非常好,但是如果你在应用中的很多地方重用模态,它可能会有点重复,所以我建议使用上下文API。为你的模态状态定义一个上下文对象,在你的应用程序顶部附近创建一个提供者,然后每当你有一个需要呈现模态的子组件时,你就可以呈现模态上下文的消费者。这样你就可以很容易地把你的模态嵌套在你的组件树中更深的地方,而不必一路向下传递回调。下面是如何做到这一点的-首先创建一个context.js文件:
context.js
// context.js import React from "react"; export const ModalContext = React.createContext();
现在更新的App.js文件:
// App.js import React from "react"; import { ModalContext } from "./context"; import Modal from "./Modal"; const App = () => { const [showModal, updateShowModal] = React.useState(false); const toggleModal = () => updateShowModal(state => !state); return ( <ModalContext.Provider value={{ showModal, toggleModal }}> <div> <h1>Not a modal</h1> <button onClick={toggleModal}>Show Modal</button> <Modal canShow={showModal} updateModalState={toggleModal} /> </div> </ModalContext.Provider> ); } export default App;
最后是更新后的Modal.js文件:
// Modal.js import React from "react"; import { ModalContext } from "./context"; const modalStyles = { position: "fixed", top: 0, left: 0, width: "100vw", height: "100vh", background: "blue" }; const Modal = () => { return ( <ModalContext.Consumer> {context => { if (context.showModal) { return ( <div style={modalStyles}> <h1>I'm a Modal!</h1> <button onClick={context.toggleModal}>Hide Me</button> </div> ); } return null; }} </ModalContext.Consumer> ); }; export default Modal;
这里有一个Codesandbox的链接,其中包含一个使用上下文的工作版本。我希望这能有所帮助!
3npbholx2#
解决这个问题的一种方法是使用css和JSX。这是一个应用程序,我可以有任何东西,比如一个按钮,一个链接,任何东西,假设我们有一个链接(react-router-dom),它将我们重定向到DeletePage删除页面呈现Modal您将提供模态的title和actions作为props
(react-router-dom)
DeletePage
Modal
title
actions
props
const App = () => { return( <Link to="/something/someid">SomeAction</Link> ) } const DeletePage = () => { return( <Modal title="Are you sure you want to delete this" dismiss={() => history.replace("/")} action={() => console.log("deleted") } /> ) }
模态
const Modal = (props) => { return( <div> <div className="background" onClick={props.dismiss}/> <h1>{props.title}</h1> <button onClick={props.dismiss}>Cancel</button> <button onClick={props.action}>Delete</button> </div> ) }
z-index
position: fixed
cancel button
Delete button
action
这个方法有一个css的缺陷,因为如果你的父组件有一个relative的position属性,那么它将被破坏。无论z索引有多高,模态都将保留在父对象内部
relative
React门户以自己的方式创建“门户您可能拥有的react代码将在id为#root的DOM内部呈现(大多数情况下)为了将Modal渲染为最顶层,我们创建了另一个DOM element例如公共index.html文件中的<div id="modal"></div>Modal react组件代码将略有更改
#root
DOM
DOM element
index.html
<div id="modal"></div>
const Modal = (props) => { return ReactDOM.createPortal( <div> <div className="background" onClick={props.dismiss}/> <h1>{props.title}</h1> <button onClick={props.dismiss}>Cancel</button> <button onClick={props.action}>Delete</button> </div> ),document.querySelector("#modal") }
休息都一样
soat7uwm3#
我一直在努力寻找一种好的、标准的方式来处理react中的模态。有些人建议使用本地状态模态,有些人建议使用模态上下文提供程序和一个函数来呈现模态窗口,或者使用像ChakraUI这样的预置ui库,它提供了自己的Modal组件。但是使用这些可能有点棘手,因为它们往往会使web ui中相对简单的概念过于复杂。经过一番研究,我已经习惯了门户的方式,因为这似乎是最明显的方式。所以这个想法是,创建一个可重用的模态组件,将子组件作为 prop ,并使用本地setState有条件地呈现每个模态。这样,与页面或组件相关的每个模态都只出现在相应的组件中。
setState
要创建使用相同设计的相似模态,可以使用一个jsx生成器函数,该函数将很少的颜色和其他属性作为其参数。工作代码:
// Generate modals for different types // All use the same design // IMPORTANT: Tailwind cannot deduce partial class names sent as arguments, and // removes them from final bundle, safe to use inline styling const _generateModal = ( initialTitle: string, image: string, buttonColor: string, bgColor: string = "white", textColor: string = "rgb(55 65 81)", buttonText: string = "Continue" ) => { return ({ title = initialTitle, text, isOpen, onClose }: Props) => { if (!isOpen) return null; return ReactDom.createPortal( <div className="fixed inset-0 bg-black bg-opacity-80"> <div className="flex h-full flex-col items-center justify-center"> <div className="relative flex h-1/2 w-1/2 flex-col items-center justify-evenly rounded-xl lg:w-1/4" style={{ color: textColor, backgroundColor: bgColor }} > <RxCross2 className="absolute top-0 right-0 mr-5 mt-5 cursor-pointer text-2xl" onClick={() => onClose()} /> <h1 className="text-center text-3xl font-thin">{title}</h1> <h3 className="text-center text-xl font-light tracking-wider opacity-80"> {text} </h3> <img src={image} alt="modal image" className="hidden w-1/6 lg:block lg:w-1/4" /> <button onClick={() => onClose()} className="rounded-full px-16 py-2 text-xl text-white" style={{ backgroundColor: buttonColor }} > {buttonText} </button> </div> </div> </div>, document.getElementById("modal-root") as HTMLElement ); }; }; export const SuccessModal = _generateModal( "Success!", checkimg, "rgb(21 128 61)" // green-700 ); export const InfoModal = _generateModal( "Hey there!", infoimg, "rgb(59 130 246)" // blue-500 ); export const ErrorModal = _generateModal( "Face-plant!", errorimg, "rgb(190 18 60)", // rose-700 "rgb(225 29 72)", // rose-600 "rgb(229 231 235)", // gray-200 "Try Again" );
3条答案
按热度按时间pkwftd7m1#
有几种方法可以做到这一点。第一种方法涉及从父组件传入模态状态。下面是如何做到这一点-首先是父
App.js
组件:下面是
Modal.js
子组件,它将呈现模态:这种方法非常好,但是如果你在应用中的很多地方重用模态,它可能会有点重复,所以我建议使用上下文API。
为你的模态状态定义一个上下文对象,在你的应用程序顶部附近创建一个提供者,然后每当你有一个需要呈现模态的子组件时,你就可以呈现模态上下文的消费者。这样你就可以很容易地把你的模态嵌套在你的组件树中更深的地方,而不必一路向下传递回调。下面是如何做到这一点的-首先创建一个
context.js
文件:现在更新的
App.js
文件:最后是更新后的
Modal.js
文件:这里有一个Codesandbox的链接,其中包含一个使用上下文的工作版本。我希望这能有所帮助!
3npbholx2#
解决这个问题的一种方法是使用css和JSX。
这是一个应用程序,我可以有任何东西,比如一个按钮,一个链接,任何东西,假设我们有一个链接
(react-router-dom)
,它将我们重定向到DeletePage
删除页面呈现
Modal
您将提供模态的title
和actions
作为props
模态
z-index
设置为较高的数字position: fixed
cancel button
也具有相同的onClick函数,该函数用于Delete button
具有通过属性传递的action
函数这个方法有一个css的缺陷,因为如果你的父组件有一个
relative
的position属性,那么它将被破坏。无论z索引有多高,模态都将保留在父对象内部
保存我们的是React之门
React门户以自己的方式创建“门户
您可能拥有的react代码将在id为
#root
的DOM
内部呈现(大多数情况下)为了将
Modal
渲染为最顶层,我们创建了另一个DOM element
例如公共index.html
文件中的<div id="modal"></div>
Modal
react组件代码将略有更改休息都一样
soat7uwm3#
使用React-Portal和模态发生器
我一直在努力寻找一种好的、标准的方式来处理react中的模态。有些人建议使用本地状态模态,有些人建议使用模态上下文提供程序和一个函数来呈现模态窗口,或者使用像ChakraUI这样的预置ui库,它提供了自己的
Modal
组件。但是使用这些可能有点棘手,因为它们往往会使web ui中相对简单的概念过于复杂。经过一番研究,我已经习惯了门户的方式,因为这似乎是最明显的方式。所以这个想法是,创建一个可重用的模态组件,将子组件作为 prop ,并使用本地
setState
有条件地呈现每个模态。这样,与页面或组件相关的每个模态都只出现在相应的组件中。奖金:
要创建使用相同设计的相似模态,可以使用一个jsx生成器函数,该函数将很少的颜色和其他属性作为其参数。
工作代码: