Как правильно создать middleware для страниц с использованием библиотеки react-router-dom?

У меня имеется AuthMiddleware, который сохраняет данные аутентификации в state store. Когда пользователь успешно вводит свои данные на странице входа (LoginPage), выполняется следующий код: <br/><br/><pre><code class="javascript">export function removeAllAuthData(dispath) {
  console.error("Remove all auth data");
  localStorage.removeItem(accessTokenInLocalStorage);
  localStorage.removeItem(isCustomerInLocalStorage);
  Cookies.remove(refreshTokenInCookies);
  Cookies.remove(userIdInCookies);

  dispath?.({
    type: clearAllAuthData,
    payload: {},
  });
}

export function AuthenticationMiddleware({ children }) {
  const dispath = useDispatch();

  useEffect(() =&gt; {
    const asyncFun = async () =&gt; {
      const refreshToken = Cookies.get(refreshTokenInCookies);
      const userId = Cookies.get(userIdInCookies);

      const accessToken = localStorage.getItem(accessTokenInLocalStorage);
      const isCustomer = localStorage.getItem(isCustomerInLocalStorage);
      const isCustomerToBool = stringToBool(isCustomer);

      console.log(refreshToken);
      console.log(userId);
      console.log(isCustomer);
      //Здесь я заметил, что они пустые

      if (
        accessToken &amp;&amp;
        refreshToken &amp;&amp;
        userId &amp;&amp;
        isCustomerToBool !== undefined
      ) {
        let type =
          isCustomerToBool === true ? addCustomerAuthData : addSellerAuthData;
        const authData = {
          userId: userId,
          refreshToken: refreshToken,
          accessToken: accessToken,
        };
        dispath({
          type: type,
          payload: authData,
        });
      } else {
        removeAllAuthData(dispath);
      }
    };
    asyncFun();
  }, [])
  • 14 ноября 2024 г. 20:03
Ответы на вопрос 1
Создание middleware для управления аутентификацией в React с использованием `react-router-dom` может помочь обеспечить доступ к защищенным страницам и обработать состояние аутентификации. В вашем случае, вы уже имеете компонент `AuthenticationMiddleware`, который загружает данные аутентификации из локального хранилища и кукисов, и взаимодействует с Redux.

Вот пример того, как правильно реализовать middleware и использовать его с `react-router-dom`:

1. **Создайте `AuthMiddleware`:**
```javascript
import React, { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import Cookies from 'js-cookie';
import { useLocation, Navigate } from 'react-router-dom';

export function removeAllAuthData(dispatch) {
  console.error("Remove all auth data");
  localStorage.removeItem(accessTokenInLocalStorage);
  localStorage.removeItem(isCustomerInLocalStorage);
  Cookies.remove(refreshTokenInCookies);
  Cookies.remove(userIdInCookies);

  dispatch?.({
    type: clearAllAuthData,
    payload: {},
  });
}

export function AuthenticationMiddleware({ children }) {
  const dispatch = useDispatch();
  const location = useLocation();
  
  useEffect(() => {
    const asyncFun = async () => {
      const refreshToken = Cookies.get(refreshTokenInCookies);
      const userId = Cookies.get(userIdInCookies);
      const accessToken = localStorage.getItem(accessTokenInLocalStorage);
      const isCustomer = localStorage.getItem(isCustomerInLocalStorage);
      const isCustomerToBool = stringToBool(isCustomer);

      if (
        accessToken &&
        refreshToken &&
        userId &&
        isCustomerToBool !== undefined
      ) {
        let actionType = isCustomerToBool ? addCustomerAuthData : addSellerAuthData;
        const authData = {
          userId: userId,
          refreshToken: refreshToken,
          accessToken: accessToken,
        };
        dispatch({
          type: actionType,
          payload: authData,
        });
      } else {
        removeAllAuthData(dispatch);
      }
    };

    asyncFun();
  }, [dispatch]);

  // Если пользователь не аутентифицирован, перенаправляем его на страницу входа
  const isAuthenticated = !!localStorage.getItem(accessTokenInLocalStorage); // Проверьте, есть ли токен
  if (!isAuthenticated) {
    return <Navigate to="/login" state={{ from: location }} replace />;
  }

  return children;
}
```

2. **Используйте `AuthMiddleware` в вашем приложении:**
   Внедрите `AuthenticationMiddleware` в `Router` вашего приложения, чтобы защищать маршруты.

```javascript
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import AuthenticationMiddleware from './AuthenticationMiddleware'; // Импортируйте ваш middleware
import LoginPage from './LoginPage';
import ProtectedPage from './ProtectedPage';

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/login" element={<LoginPage />} />
        <Route
          path="/protected"
          element={
            <AuthenticationMiddleware>
              <ProtectedPage />
            </AuthenticationMiddleware>
          }
        />
        {/* Другие маршруты */}
      </Routes>
    </Router>
  );
}

export default App;
```

### Объяснение:

- **`AuthenticationMiddleware`**: Этот компонент проверяет наличие токенов аутентификации и обновляет состояние аутентификации в Redux. Если данные аутентификации отсутствуют, пользователь будет перенаправлен на страницу логина.
  
- **`useLocation`**: Используется для сохранения текущего маршрута. Это важно, если вы хотите перенаправить пользователя обратно после успешного входа.

- **`Navigate`**: Используется для перенаправления пользователя на страницу входа, если он не аутентифицирован.

### Важные замечания:
- Убедитесь, что ваши токены корректно устанавливаются и удаляются в соответствии с действиями пользователя.
- Оберните любые страницы, которые должны быть защищены, в `AuthenticationMiddleware`.
Похожие вопросы