Как в React реализовать переход на другую страницу только для пользователей, использующих десктопные устройства?

Здравствуйте, <br/> У меня есть пет-проект, который я разрабатываю с использованием TypeScript и React, а также React Router. <br/> <br/> Согласно заданию, на главной странице отображаются продукты, и у каждого продукта имеется кнопка "Заказать". При нажатии на эту кнопку снизу появляется выдвижная панель (sheet) с информацией о конкретном продукте и вариантами оплаты, включая кнопки "Отменить оплату" и "Оплатить". <br/> <br/> <i>Когда пользователь нажимает кнопку "Оплатить", он перенаправляется на страницу с деталями оплаты. У меня есть две страницы для оплаты, и в зависимости от выбранного способа оплаты открывается соответствующая страница.</i> <br/> <br/> <b>И вот главный вопрос:</b> согласно макету и заданию, на десктопной версии, когда пользователь нажимает "Оплатить", он переходит на новую страницу, где продолжается процесс оплаты, реализованный мной. Однако для мобильных устройств при нажатии на кнопку "Оплатить" пользователь не должен перенаправляться на страницу; вместо этого должна открываться еще одна выдвижная панель с деталями оплаты (которая в десктопной версии реализована на отдельной странице). <br/> <br/> Мне не совсем понятно, как технически реализовать это поведение: как сделать так, чтобы на десктопе пользователь переходил на новую страницу, а на мобильных устройствах — открывалась выдвижная панель?
  • 10 марта 2025 г. 18:54
Ответы на вопрос 2
Чтобы реализовать различное поведение для десктопных и мобильных устройств в React с использованием React Router, вы можете воспользоваться проверкой размера экрана. Для этого удобно использовать хук `useEffect` совместно с `useState`, а также библиотеку `react-responsive` для упрощенного определения текущего устройства.

Вот пример того, как вы можете реализовать требуемое поведение:

1. Установите библиотеку `react-responsive`, если её у вас нет:

```bash
npm install react-responsive
```

2. Создайте компонент для кнопки "Оплатить":

```tsx
import React from "react";
import { useHistory } from "react-router-dom";
import { useMediaQuery } from "react-responsive";

interface PaymentButtonProps {
  paymentMethod: string; // или другой тип данных, который вам нужен
  productId: string; // ID продукта
}

const PaymentButton: React.FC<PaymentButtonProps> = ({ paymentMethod, productId }) => {
  const history = useHistory();
  const isDesktop = useMediaQuery({ minWidth: 1024 }); // Задайте здесь порог для десктопных устройств

  const handlePayment = () => {
    if (isDesktop) {
      // Для десктопа переходим на другую страницу
      history.push(`/payment/${paymentMethod}/${productId}`);
    } else {
      // Для мобильных устройств открываем выдвижную панель
      // Здесь вы вызываете метод для открытия панели
      openBottomSheet(paymentMethod, productId);
    }
  };

  const openBottomSheet = (paymentMethod: string, productId: string) => {
    // Логика открытия вашей выдвижной панели
    console.log("Открыть выдвижную панель с метом:", paymentMethod, "и продуктом:", productId);
  };

  return <button onClick={handlePayment}>Оплатить</button>;
};

export default PaymentButton;
```

3. Используйте этот компонент в вашем приложении:

```tsx
<PaymentButton paymentMethod="credit-card" productId="1234" />
```

### Пояснение:
- Мы используем `useMediaQuery` из `react-responsive`, чтобы определить, является ли устройство десктопом. В данном примере, порог для десктопа установлен на 1024 пикселя, но вы можете изменить его в зависимости от ваших требований.
- При нажатии на кнопку "Оплатить" происходит проверка: если это десктоп, происходит редирект на новую страницу, а если это мобильное устройство, вызывается функция для открытия выдвижной панели.
- Логика открытия панели будет зависеть от того, как вы её реализуете в вашем приложении.

### Примечание:
Убедитесь, что вы корректно обрабатываете состоянии (например, можно использовать кнопки для открытия и закрытия панели, а также передавать нужные данные для отображения).
Самый простой и часто используемый способ — проверять ширину экрана. Например, если window.innerWidth < 768, считаем, что это «мобильный» режим, а если больше — «десктоп». Либо использовать любые другие «брейкпоинты», которые вам подходят. 

// Псевдокод, показывающий идею

const handlePayClick = () => {
  // Проверяем ширину экрана
  if (window.innerWidth < 768) {
    // Открываем выдвижную панель с деталями оплаты
    setIsSecondSheetOpen(true);
  } else {
    // Переходим на другую страницу (Desktop-версия)
    navigate('/payment');
  }
};


Есть еще вариант использовать библиотеку react-responsive и ее хук useMediaQuery:

import { useMediaQuery } from 'react-responsive';

function YourComponent() {
  // Определяем, что это мобильная версия, если ширина экрана меньше 768
  const isMobile = useMediaQuery({ query: '(max-width: 768px)' });

  const handlePayClick = () => {
    if (isMobile) {
      setIsSecondSheetOpen(true);
    } else {
      navigate('/payment');
    }
  };

  return (
    <button onClick={handlePayClick}>
      Оплатить
    </button>
  );
}


По сути, два этих варианта подойдут в контексте текущей задачи, какой использовать - решать уже вам, но я бы предпочел второй через react-responsive
Похожие вопросы