Защищенные маршруты в реагирующем маршрутизаторе dom 6

Я создал простой пользовательский контекст в реакции:

ПользовательПровайдер

export const AuthContext = createContext();


export const AuthProvider = ({children}) => {
  const [user, setUser] = useState(null);

  useEffect(() => {
   
      //Call server
      const loginUser = {
        userId: 1,
        role: "Admin"
      }
      setUser(loginUser)
    }, []);

  return (
    <AuthContext.Provider value = {{user}}  >{children}</AuthContext.Provider>
  );
};

useAuth

const useAuth = () => {
    const user = useContext(AuthContext);
    if (user === undefined) {
      throw new Error('useAuth must be used within an AuthProvider');
    }
    return user;
};

export default useAuth;

Приложение

  return (
    <AuthProvider>
      <BrowserRouter>
        <Routes>
          <Route path = "/Login" element = {<Login/>}/>
          <Route element = {<ProtectedRoutes />}>
            <Route path = "/User/Profile" element = {<Profile/>}/>
          </Route>
        </Routes>
      </BrowserRouter>
    </AuthProvider>
  );

Защищенные маршруты

const ProtectedRoutes = () => {
  const {user} = useAuth();

  return(
    user ? <Outlet/> : <Navigate to = "/login"/>
  )

}

export default ProtectedRoutes

Все работает нормально, но когда я обновляю страницу в User/Profile, когда пользователь вошел в систему, он все равно перенаправляет меня на вход в систему. Журнал консоли в защищенных маршрутах, когда я обновляю страницу, выглядит так:

null
{userId: 1, role: 'Admin'}

Я знаю, что эта проблема, вероятно, возникает из-за того, что «пользователь» имеет значение null при первом отображении, но я понятия не имею, как это исправить. Может ли кто-нибудь сказать мне, как я могу это улучшить?

🤔 А знаете ли вы, что...
React поддерживает создание анимаций и переходов между состояниями.


144
1

Ответ:

Решено

Вы можете сохранить состояние приложения и перенаправить только тогда, когда приложение аутентифицировано

Вот хорошая статья Кента С. Доддса о том, как обрабатывать аутентификацию .

export const AuthContext = createContext();


export const AuthProvider = ({children}) => {

  const [appState, setAppState] = useState({ user: null, state: 'loading' });

  useEffect(() => {
   
      //Call server
      const loginUser = {
        userId: 1,
        role: "Admin"
      }
      setUser({
         user: loginUser,
         state: 'loaded'
      })
    }, []);

  return (
    <AuthContext.Provider value = {appState}  >{children}</AuthContext.Provider>
  );
};


const useAuth = () => {
    const state = useContext(AuthContext);
    if (state === undefined) {
      throw new Error('useAuth must be used within an AuthProvider');
    }
    return { ...state };
};

export default useAuth;

обработка состояния приложения в ProtectedRoutes

const ProtectedRoutes = () => {

  const { user, state } = useAuth();

  if (state === 'loading') {
    return <div>Loading...</div>
  }

  return(
    user ? <Outlet/> : <Navigate to = "/login"/>
  )

}

export default ProtectedRoutes

Или рендеринг защищенных маршрутов только после загрузки приложения

const AppRoutes = () => {

   const { user, state } = useAuth();
   
   if (state === 'loading') {
       return <div>Loading...</div>
   }   

   return user ? 
     <AuthenticatedRoutes>
     : UnAuthenticatedRoutes />

}

  return (
    <AuthProvider>
      <BrowserRouter>
            <AppRoutes />
        </Routes>
      </BrowserRouter>
    </AuthProvider>
  );

Надеюсь, это как-то поможет