Работа с порталами в React: создание модальных окон и всплывающих сообщений

В этой статье мы рассмотрим, как использовать порталы в React для создания модальных окон и всплывающих сообщений.

Одной из самых интересных и полезных функциональностей React является работа с порталами. В этой статье мы рассмотрим, как создать модальные окна и всплывающие сообщения с использованием порталов в функциональных компонентах React. Порталы в React позволяют отрендерить дочерний компонент в другой DOM элемент, который находится вне иерархии компонента. Это может быть полезно, когда требуется рендерить компоненты в других частях страницы или даже вне контейнера приложения. Для начала, установим все необходимые зависимости. Откройте командную строку и выполните следующую команду:
npm install react-dom
Окончив установку, импортируйте ReactDOM в файле компонента:
import ReactDOM from 'react-dom';
Теперь давайте создадим простой модальный компонент. Создайте новый файл Modal.js и добавьте следующий код:
import React from 'react';

const Modal = ({ isOpen, onClose, children }) => {
  if (!isOpen) {
    return null;
  }

  return ReactDOM.createPortal(
    <div className="modal">
      <div className="modal-content">{children}</div>
      <button onClick={onClose}>Закрыть</button>
    </div>,
    document.getElementById('modal-root')
  );
};

export default Modal;
В этом компоненте мы используем ReactDOM.createPortal для отображения содержимого модального окна в элементе с идентификатором 'modal-root'. Помните, что этот элемент должен быть добавлен в HTML файл вашего проекта:
<body>
  <div id="root"></div>
  <div id="modal-root"></div>
</body>
Теперь создадим компонент, который будет использовать модальное окно. Создайте новый файл App.js и добавьте следующий код:
import React, { useState } from 'react';
import Modal from './Modal';

const App = () => {
  const [isOpen, setIsOpen] = useState(false);

  const handleOpenModal = () => {
    setIsOpen(true);
  };

  const handleCloseModal = () => {
    setIsOpen(false);
  };

  return (
    <div>
      <button onClick={handleOpenModal}>Открыть модальное окно</button>
      <Modal isOpen={isOpen} onClose={handleCloseModal}>
        <h1>Модальное окно</h1>
        <p>Это модальное окно!</p>
      </Modal>
    </div>
  );
};

export default App;
В этом компоненте мы используем useState для создания состояния isOpen, которое определяет, открыто ли модальное окно или нет. При нажатии на кнопку "Открыть модальное окно" состояние isOpen устанавливается в true, что вызывает рендеринг модального окна. Когда модальное окно закрывается, состояние isOpen устанавливается в false. Теперь, чтобы отобразить наше приложение, импортируйте компонент App в файл index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));
Теперь, если вы запустите свое приложение React, вы должны увидеть кнопку "Открыть модальное окно". При нажатии на эту кнопку откроется модальное окно с заголовком "Модальное окно" и текстом "Это модальное окно!". Если вы нажмете на кнопку "Закрыть", модальное окно закроется.
Теперь давайте рассмотрим, как создать всплывающие сообщения с использованием порталов. Создайте новый файл Toast.js и добавьте следующий код:
import React from 'react';
import ReactDOM from 'react-dom';

const Toast = ({ message }) => {
  return ReactDOM.createPortal(
    <div className="toast">{message}</div>,
    document.getElementById('toast-root')
  );
};

export default Toast;
В этом компоненте мы используем ReactDOM.createPortal для отображения всплывающего сообщения в элементе с идентификатором 'toast-root'. Помимо сообщения, мы можем редактировать стили внутри компонента toast, чтобы обеспечить пользовательскую информацию и удобство использования. Добавьте следующий код в компонент App.js, чтобы использовать всплывающее сообщение:
import React, { useState } from 'react';
import Modal from './Modal';
import Toast from './Toast';

const App = () => {
  const [isOpen, setIsOpen] = useState(false);
  const [showToast, setShowToast] = useState(false);

  const handleOpenModal = () => {
    setIsOpen(true);
  };

  const handleCloseModal = () => {
    setIsOpen(false);
  };

  const handleShowToast = () => {
    setShowToast(true);
    setTimeout(() => {
      setShowToast(false);
    }, 2000);
  };

  return (
    <div>
      <button onClick={handleOpenModal}>Открыть модальное окно</button>
      <button onClick={handleShowToast}>Показать всплывающее сообщение</button>
      <Modal isOpen={isOpen} onClose={handleCloseModal}>
        <h1>Модальное окно</h1>
        <p>Это модальное окно!</p>
      </Modal>
      {showToast && <Toast message="Привет, я всплывающее сообщение!" />}
    </div>
  );
};

export default App;
В этом коде мы добавили новое состояние showToast, которое определяет, должно ли отображаться всплывающее сообщение или нет. При нажатии на кнопку "Показать всплывающее сообщение" состояние showToast становится true и всплывающее сообщение отображается. Через 2 секунды после отображения сообщение исчезает, так как мы используем setTimeout в функции handleShowToast. Добавьте элемент toast-root в ваш html-файл, также как и с элементом modal-root:
<body>
  <div id="root"></div>
  <div id="modal-root"></div>
  <div id="toast-root"></div>
</body>
Теперь, при запуске приложения и нажатии на кнопку "Показать всплывающее сообщение", вы должны увидеть всплывающее сообщение с текстом "Привет, я всплывающее сообщение!". Через 2 секунды оно исчезнет автоматически. Поздравляю, вы только что освоили работу с порталами React и создали модальные окна и всплывающие сообщения в функциональных компонентах React. Теперь вы можете использовать эти знания в своих проектах, чтобы создавать лучший пользовательский интерфейс.