Я создал простой пользовательский контекст в реакции:
ПользовательПровайдер
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 поддерживает создание анимаций и переходов между состояниями.
Вы можете сохранить состояние приложения и перенаправить только тогда, когда приложение аутентифицировано
Вот хорошая статья Кента С. Доддса о том, как обрабатывать аутентификацию .
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>
);
Надеюсь, это как-то поможет