rkdrnf / react-modal-state

Easily manipulate modals in react
14 stars 1 forks source link
contextapi hooks modal react state

React Modal State

This is a tiny library that manages modal in react with minimal dependency.

[!IMPORTANT]
This library is in an early stage. Any issue or feature request would be very helpful to develop this library further!

Installation

npm i react-modal-state

Usage

Place ModalProvider and ModalRenderer

import { ModalProvider, ModalRenderer } from "react-modal-state";

...

// Optionally provide modals prop to open modal by id or to use self-nested modals
<ModalProvider modals={[
        ["users/:id", UserModal],
      ]}
    >
    <App />
    <ModalRenderer Component={NewUserModal} />
    <ModalRenderer Component={UserModal} />
</ModalProvider>

[!NOTE]
<ModalRenderer /> does not have to be the direct child of the <ModalProvider />. You can place <ModalRenderer /> in any node under <ModalProvider /> component tree if needed.

Open from anywhere

import { useModal } from "react-modal-state";

function Content() {
  const { open: openNewUser } = useModal(NewUserModal);
  const { open: openUser } = useModal(UserModal);
  // or alternatively, you can open modal by id defined in ModalProvider
  // const { open: openUser } = useModal("users/:id");

  return (
    <>
      <button onClick={() => openNewUser()}>New User</button>
      <button onClick={() => openUser({ id: 1, name: "Steve" })}>User 1</button>
    </>
  );
}

Declare modal component

import { useModalInstance } from "react-modal-state";

const UserModal = () => {
  const { data, isOpen, close } = useModalInstance<{
    id: number;
    name: string;
  }>();

  return (
    <Dialog open={isOpen} onClose={close}>
      <DialogTitle>User {data.id}</DialogTitle>
      <DialogContent>
        {data.name}'s profile
      </DialogContent>
    </Dialog>
  );
};

Features

Backgrounds

There are many awkward and repetitive points when using modals naively and this library tries to solve these problems.

Typical scenarios are as below.

Using this library, you can solve above situations elegantly.

Below is an minimal example code using this library (with dialog component from MUI)

const NewUserModal = () => {
  const { isOpen, close } = useModalInstance();

  return (
    <Dialog open={isOpen} onClose={close}>
      <DialogTitle>New User</DialogTitle>
      <DialogContent>
        <Box>Create new user</Box>
      </DialogContent>
    </Dialog>
  );
};

const UserModal = () => {
  const { data, isOpen, close } = useModalInstance<{
    id: number;
    name: string;
  }>();

  const { open: openUser } = useModal(`users/:id`);

  return (
    <Dialog open={isOpen} onClose={close}>
      <DialogTitle>User {data.id}</DialogTitle>
      <DialogContent>
        {data.name}'s profile
      </DialogContent>
    </Dialog>
  );
};

function Content() {
  const { open: openNewUser } = useModal("new-user");
  const { open: openUser } = useModal("users/:id");

  return (
    <Box>
      <button onClick={() => openNewUser()}>New User</button>
      <button onClick={() => openUser({ id: 1, name: "Steve" })}>User 1</button>
    </Box>
  );
}

function App() {
  return (
    <ModalProvider
      modals={[
        ["new-user", NewUserModal],
        ["users/:id", UserModal],
      ]}
    >
      <Content />
      <ModalRenderer Component={NewUserModal} />
      <ModalRenderer Component={UserModal} />
    </ModalProvider>
  );
}

In the above code, you can see benefits like

Demo and Development

This is a typical vite project.

npm install
npm run dev

to run demo page.