mirror of
https://github.com/LCTT/TranslateProject.git
synced 2024-12-26 21:30:55 +08:00
a9f014a63b
sources/tech/20210524 4 steps to set up global modals in React.md
337 lines
11 KiB
Markdown
337 lines
11 KiB
Markdown
[#]: subject: (4 steps to set up global modals in React)
|
||
[#]: via: (https://opensource.com/article/21/5/global-modals-react)
|
||
[#]: author: (Ajay Pratap https://opensource.com/users/ajaypratap)
|
||
[#]: collector: (lujun9972)
|
||
[#]: translator: ( )
|
||
[#]: reviewer: ( )
|
||
[#]: publisher: ( )
|
||
[#]: url: ( )
|
||
|
||
4 steps to set up global modals in React
|
||
======
|
||
Learn how to create interactive pop-up windows in a React web app.
|
||
![Digital creative of a browser on the internet][1]
|
||
|
||
A modal dialog is a window that appears on top of a web page and requires a user's interaction before it disappears. [React][2] has a couple of ways to help you generate and manage modals with minimal coding.
|
||
|
||
If you create them within a **local scope**, you must import modals into each component and then create a state to manage each modal's opening and closing status.
|
||
|
||
By using a **global state**, you don't need to import modals into each component, nor do you have to create a state for each. You can import all the modals in one place and use them anywhere.
|
||
|
||
In my opinion, the best way to manage modal dialogs in your React application is globally by using a React context rather than a local state.
|
||
|
||
### How to create global modals
|
||
|
||
Here are the steps (and code) to set up global modals in React. I'm using [Patternfly][3] as my foundation, but the principles apply to any project.
|
||
|
||
#### 1\. Create a global modal component
|
||
|
||
In a file called **GlobalModal.tsx**, create your modal definition:
|
||
|
||
|
||
```
|
||
import React, { useState, createContext, useContext } from 'react';
|
||
import { CreateModal, DeleteModal,UpdateModal } from './components';
|
||
|
||
export const MODAL_TYPES = {
|
||
CREATE_MODAL:”CREATE_MODAL”,
|
||
DELETE_MODAL: “DELETE_MODAL”,
|
||
UPDATE_MODAL: “UPDATE_MODAL”
|
||
};
|
||
|
||
const MODAL_COMPONENTS: any = {
|
||
[MODAL_TYPES.CREATE_MODAL]: CreateModal,
|
||
[MODAL_TYPES.DELETE_MODAL]: DeleteModal,
|
||
[MODAL_TYPES.UPDATE_MODAL]: UpdateModal
|
||
};
|
||
|
||
type GlobalModalContext = {
|
||
showModal: (modalType: string, modalProps?: any) => void;
|
||
hideModal: () => void;
|
||
store: any;
|
||
};
|
||
|
||
const initalState: GlobalModalContext = {
|
||
showModal: () => {},
|
||
hideModal: () => {},
|
||
store: {},
|
||
};
|
||
|
||
const GlobalModalContext = createContext(initalState);
|
||
export const useGlobalModalContext = () => useContext(GlobalModalContext);
|
||
|
||
export const GlobalModal: React.FC<{}> = ({ children }) => {
|
||
const [store, setStore] = useState();
|
||
const { modalType, modalProps } = store || {};
|
||
|
||
const showModal = (modalType: string, modalProps: any = {}) => {
|
||
setStore({
|
||
...store,
|
||
modalType,
|
||
modalProps,
|
||
});
|
||
};
|
||
|
||
const hideModal = () => {
|
||
setStore({
|
||
...store,
|
||
modalType: null,
|
||
modalProps: {},
|
||
});
|
||
};
|
||
|
||
const renderComponent = () => {
|
||
const ModalComponent = MODAL_COMPONENTS[modalType];
|
||
if (!modalType || !ModalComponent) {
|
||
return null;
|
||
}
|
||
return <ModalComponent id="global-modal" {...modalProps} />;
|
||
};
|
||
|
||
return (
|
||
<GlobalModalContext.Provider value={{ store, showModal, hideModal }}>
|
||
{renderComponent()}
|
||
{children}
|
||
</GlobalModalContext.Provider>
|
||
);
|
||
};
|
||
```
|
||
|
||
In this code, all dialog components are mapped with the modal type. The `showModal` and `hideModal` functions are used to open and close dialog boxes, respectively.
|
||
|
||
The `showModal` function takes two parameters: `modalType` and `modalProps`. The `modalProps` parameter is optional; it is used to pass any type of data to the modal as a prop.
|
||
|
||
The `hideModal` function doesn't have any parameters; calling it causes the current open modal to close.
|
||
|
||
#### 2\. Create modal dialog components
|
||
|
||
In a file called **CreateModal.tsx**, create a modal:
|
||
|
||
|
||
```
|
||
import React from "react";
|
||
import { Modal, ModalVariant, Button } from "@patternfly/react-core";
|
||
import { useGlobalModalContext } from "../GlobalModal";
|
||
|
||
export const CreateModal = () => {
|
||
const { hideModal, store } = useGlobalModalContext();
|
||
const { modalProps } = store || {};
|
||
const { title, confirmBtn } = modalProps || {};
|
||
|
||
const handleModalToggle = () => {
|
||
hideModal();
|
||
};
|
||
|
||
return (
|
||
<Modal
|
||
variant={ModalVariant.medium}
|
||
title={title || "Create Modal"}
|
||
isOpen={true}
|
||
onClose={handleModalToggle}
|
||
actions={[
|
||
<Button key="confirm" variant="primary" onClick={handleModalToggle}>
|
||
{confirmBtn || "Confirm button"}
|
||
</Button>,
|
||
<Button key="cancel" variant="link" onClick={handleModalToggle}>
|
||
Cancel
|
||
</Button>
|
||
]}
|
||
>
|
||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
|
||
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
|
||
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
|
||
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
|
||
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
|
||
cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id
|
||
est laborum.
|
||
</Modal>
|
||
);
|
||
};
|
||
```
|
||
|
||
This has a custom hook, `useGlobalModalContext`, that provides store object from where you can access all the props and the functions `showModal` and `hideModal`. You can close the modal by using the `hideModal` function.
|
||
|
||
To delete a modal, create a file called **DeleteModal.tsx**:
|
||
|
||
|
||
```
|
||
import React from "react";
|
||
import { Modal, ModalVariant, Button } from "@patternfly/react-core";
|
||
import { useGlobalModalContext } from "../GlobalModal";
|
||
|
||
export const DeleteModal = () => {
|
||
const { hideModal } = useGlobalModalContext();
|
||
|
||
const handleModalToggle = () => {
|
||
hideModal();
|
||
};
|
||
|
||
return (
|
||
<Modal
|
||
variant={ModalVariant.medium}
|
||
title="Delete Modal"
|
||
isOpen={true}
|
||
onClose={handleModalToggle}
|
||
actions={[
|
||
<Button key="confirm" variant="primary" onClick={handleModalToggle}>
|
||
Confirm
|
||
</Button>,
|
||
<Button key="cancel" variant="link" onClick={handleModalToggle}>
|
||
Cancel
|
||
</Button>
|
||
]}
|
||
>
|
||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
|
||
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
|
||
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
|
||
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
|
||
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
|
||
cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id
|
||
est laborum.
|
||
</Modal>
|
||
);
|
||
};
|
||
```
|
||
|
||
To update a modal, create a file called **UpdateModal.tsx** and add this code:
|
||
|
||
|
||
```
|
||
import React from "react";
|
||
import { Modal, ModalVariant, Button } from "@patternfly/react-core";
|
||
import { useGlobalModalContext } from "../GlobalModal";
|
||
|
||
export const UpdateModal = () => {
|
||
const { hideModal } = useGlobalModalContext();
|
||
|
||
const handleModalToggle = () => {
|
||
hideModal();
|
||
};
|
||
|
||
return (
|
||
<Modal
|
||
variant={ModalVariant.medium}
|
||
title="Update Modal"
|
||
isOpen={true}
|
||
onClose={handleModalToggle}
|
||
actions={[
|
||
<Button key="confirm" variant="primary" onClick={handleModalToggle}>
|
||
Confirm
|
||
</Button>,
|
||
<Button key="cancel" variant="link" onClick={handleModalToggle}>
|
||
Cancel
|
||
</Button>
|
||
]}
|
||
>
|
||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
|
||
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
|
||
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
|
||
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
|
||
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
|
||
cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id
|
||
est laborum.
|
||
</Modal>
|
||
);
|
||
};
|
||
```
|
||
|
||
#### 3\. Integrate GlobalModal into the top-level component in your application
|
||
|
||
To integrate the new modal structure you've created into your app, you just import the global modal class you've created. Here's my sample **App.tsx** file:
|
||
|
||
|
||
```
|
||
import "@patternfly/react-core/dist/styles/base.css";
|
||
import "./fonts.css";
|
||
import { GlobalModal } from "./components/GlobalModal";
|
||
import { AppLayout } from "./AppLayout";
|
||
|
||
export default function App() {
|
||
return (
|
||
<GlobalModal>
|
||
<AppLayout />
|
||
</GlobalModal>
|
||
);
|
||
}
|
||
```
|
||
|
||
App.tsx is the top-level component in your app, but you can add another component according to your application's structure. However, make sure it is one level above where you want to access modals.
|
||
|
||
`GlobalModal` is the root-level component where all your modal components are imported and mapped with their specific `modalType`.
|
||
|
||
#### 4\. Select the modal's button from the AppLayout component
|
||
|
||
Adding a button to your modal with **AppLayout.js**:
|
||
|
||
|
||
```
|
||
import React from "react";
|
||
import { Button, ButtonVariant } from "@patternfly/react-core";
|
||
import { useGlobalModalContext, MODAL_TYPES } from "./components/GlobalModal";
|
||
|
||
export const AppLayout = () => {
|
||
const { showModal } = useGlobalModalContext();
|
||
|
||
const createModal = () => {
|
||
showModal(MODAL_TYPES.CREATE_MODAL, {
|
||
title: "Create instance form",
|
||
confirmBtn: "Save"
|
||
});
|
||
};
|
||
|
||
const deleteModal = () => {
|
||
showModal(MODAL_TYPES.DELETE_MODAL);
|
||
};
|
||
|
||
const updateModal = () => {
|
||
showModal(MODAL_TYPES.UPDATE_MODAL);
|
||
};
|
||
|
||
return (
|
||
<>
|
||
<Button variant={ButtonVariant.primary} onClick={createModal}>
|
||
Create Modal
|
||
</Button>
|
||
<br />
|
||
<br />
|
||
<Button variant={ButtonVariant.primary} onClick={deleteModal}>
|
||
Delete Modal
|
||
</Button>
|
||
<br />
|
||
<br />
|
||
<Button variant={ButtonVariant.primary} onClick={updateModal}>
|
||
Update Modal
|
||
</Button>
|
||
</>
|
||
);
|
||
};
|
||
```
|
||
|
||
There are three buttons in the AppLayout component: create modal, delete modal, and update modal. Each modal is mapped with the corresponding `modalType`: `CREATE_MODAL`, `DELETE_MODAL`, or `UPDATE_MODAL`.
|
||
|
||
### Use global dialogs
|
||
|
||
Global modals are a clean and efficient way to handle dialogs in React. They are also easier to maintain in the long run. The next time you set up a project, keep these tips in mind.
|
||
|
||
If you'd like to see the code in action, I've included the [complete application][4] I created for this article in a sandbox.
|
||
|
||
Leslie Hinson sits down with Andrés Galante, an expert HTML and CSS coder who travels the world...
|
||
|
||
--------------------------------------------------------------------------------
|
||
|
||
via: https://opensource.com/article/21/5/global-modals-react
|
||
|
||
作者:[Ajay Pratap][a]
|
||
选题:[lujun9972][b]
|
||
译者:[译者ID](https://github.com/译者ID)
|
||
校对:[校对者ID](https://github.com/校对者ID)
|
||
|
||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||
|
||
[a]: https://opensource.com/users/ajaypratap
|
||
[b]: https://github.com/lujun9972
|
||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_web_internet_website.png?itok=g5B_Bw62 (Digital creative of a browser on the internet)
|
||
[2]: https://reactjs.org/
|
||
[3]: https://www.patternfly.org/v4/
|
||
[4]: https://codesandbox.io/s/affectionate-pine-gib74
|