DevGang
Авторизоваться

Как реализовать модальное окно с помощью React Router v6

Привет! Я искал, как реализовать Modal в React Router v6, но, к сожалению, полученные результаты не соответствовали моим потребностям. В обучающих блогах, с которыми я столкнулся, использовались JSX Routes, а я использую createBrowserRouter для управления своим стеком истории. После некоторых поисков и попыток заставить его работать, я наконец заставил его работать.

Если вы хотите создать приведенный выше пример GIF, но в React V6 и используете createBrowserRouter, то это руководство для вас.

Вот как я это сделал.

В приведенном ниже руководстве основное внимание будет уделено реализации modal, у которого нет навигационной панели, как на изображении выше.

Начало

Перво-наперво, вам нужно создать приложение react и установить react-router-dom и запустить npm install для запуска.

Давайте начнем со структуры папок. Просто скопируйте расположение моих файлов и папок, приведенное ниже:

/src
  /components
   Modal.js
  /data
   dummy-data.js
  /pages
   Gallery.jsx
  App.jsx

dummy-data.js

export const images = [
  {
    id: 1,
    thumbnail:
      'https://images.unsplash.com/photo-1682685797886-79020b7462a4?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDF8MHxlZGl0b3JpYWwtZmVlZHwxfHx8ZW58MHx8fHx8',
    fullSize:
      'https://images.unsplash.com/photo-1682685797886-79020b7462a4?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
    details: 'Details about Image 1',
  },
  {
    id: 2,
    fullSize:
      'https://images.unsplash.com/photo-1706028024882-0b972506d02d?q=80&w=1964&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
    thumbnail:
      'https://images.unsplash.com/photo-1706028024882-0b972506d02d?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwzfHx8ZW58MHx8fHx8',
    details: 'Details about Image 2',
  },
];

dummy-data.js содержит объект массива, который будет использоваться в качестве фиктивных данных. id будет уникальным идентификатором нашего изображения, который будет использоваться позже для получения подробной информации об изображении.

Modal.jsx

import { useEffect, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { images } from '../data/dummy-data';

const Modal = () => {
  const { id: imageId } = useParams();
  const navigate = useNavigate();

  const [imageData, setImageData] = useState({});

  useEffect(() => {
    const image = images.find(({ id }) => imageId == id);

    setImageData(image);
  }, [imageId]);

  const handleOnClose = () => {
    navigate('/');
  };

  return (
    <>
      {imageData && (
        <div className="modal">
          <div className="modal-content">
            <img src={imageData.fullSize} alt="Full Size" />
            <p>{imageData.details}</p>
            <button onClick={handleOnClose}>Close</button>
          </div>
        </div>
      )}
    </>
  );
};

export default Modal;

Modal.jsx — это функциональный компонент, который будет использоваться в качестве всплывающего окна для просмотра деталей конкретного изображения.

Объявления переменных:

imageId: извлекает идентификатор из маршрута с помощью useParams(). Это уникальный идентификатор изображения, отображаемого в модальном окне.

navigate Предоставляет функцию для навигации между страницами с помощью useNavigate().

Управление состоянием:

imageData представляет состояние хранения информации о выбранном изображении.

useEffect используется для получения сведений об изображении при монтировании компонента или изменении imageId. Он находит соответствующее изображение в объекте массива images (импортированном из фиктивных данных).

Закрыть модальную функцию:

handleOnClose определяет функцию для закрытия модели путем возврата к корневому пути ('/) с помощью функции navigate.

Модальный рендеринг:

Компонент отображает модальное окно только в том случае, если imageData правдива (т. е. изображение найдено). Внутри модального окна отображается полноразмерное изображение, дополнительные сведения и кнопка закрытия.

Gallery.jsx

import React from 'react';
import { useNavigate } from 'react-router-dom';
import { images } from '../data/dummy-data';
import Modal from '../components/Modal';

const Gallery = () => {
  const navigate = useNavigate();

  const viewImage = (image) => {
    const id = image.id;
    navigate('/view/' + id);
  };

  return (
    <div className="gallery">
      {images.map((image, index) => (
        <button
          key={image.id}
          className="gallery-item"
          onClick={() => viewImage(image)}
        >
          <img src={image.thumbnail} alt={`Thumbnail ${index + 1}`} />
        </button>
      ))}

      <Modal />
    </div>
  );
};

export default Gallery;

Gallery.jsx отвечает за отображение галереи изображений с предварительным просмотром миниатюр. Внутри компонента он сопоставляет объект массива изображений из фиктивных данных. Каждая кнопка имеет обработчик события нажатия (onClick), который вызывает функцию viewImage с соответствующим изображением.

Функция viewImage принимает параметр объекта изображения на основе щелчка по миниатюре и извлекает свойство id из объекта изображения. Затем он переходит к маршруту view/:id.

Компонент Modal отображается в конце компонента Gallery. Он включен для обеспечения модальной функциональности для просмотра подробной информации о выбранном изображении.

App.jsx

import React from 'react';
import Gallery from './pages/gallery';
import { createBrowserRouter, RouterProvider } from 'react-router-dom';

const router = createBrowserRouter([
  {
    path: '/',
    element: <Gallery />,
    children: [
      {
        path: 'view/:id',
        element: null,
      },
    ],
  },
]);

function App() {
  return (
    <React.StrictMode>
      <RouterProvider router={router} />
    </React.StrictMode>
  );
}

export default App;

createBrowserRouter — рекомендуемый маршрутизатор для всех веб-проектов React Router. Он использует API истории DOM для обновления URL-адреса и управления стеком истории.

Основной маршрутизатор для приведенного выше кода указан с помощью path: '/' и настроен на отрисовку компонента Gallery.

Кроме того, существует дочерний маршрут, определенный с помощью path: 'view/:id', но элементу, связанному с ним, присвоено значение null.

Компонент RouterProvider используется для предоставления экземпляра маршрутизатора (router) всему дереву компонентов React. Это крайне важно для включения функции маршрутизации.

Краткое объяснение

У нас есть родительский маршрут index, и у него есть дочерний маршрут view/:id, который отображает нулевой элемент. Если мы перейдем к этому маршруту, родительский элемент сохранит свою текущую позицию. Причина этого в том, что у нас нет <Outlet /> для отображения дочерних элементов родительского маршрута. Таким образом, он просто останется в том месте, где мы запускаем навигацию. Причина, по которой отображается Modal, заключается в том, что у нас есть useEffect, который срабатывает при изменении gallery/:id. Он сработает, только если мы щелкнем по миниатюрам, которые запускают обновление URL.

Вот и все! Я надеюсь, что это было полезно. Если у вас есть какие-либо вопросы, не стесняйтесь задавать. Спасибо за чтение!

Живая демонстрация

Исходный код с навигационной панелью

Только модель исходного кода

Источник:

#JavaScript #React
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу