I have MERN application which uses http only cookies with jwt as an authentication. I made a provider in React to hold the user information. There are also protected routes on the front-end. On the backend I have a route which returns the current user if a cookie is present else I set the user to null. When the app starts, refreshes or the user changes I make this call. Everything works as expected.
The problem appears when I refresh the page or use the url bar to manually navigate to a certain page. Because in both cases the app refreshes there is a short amount of time where a user is not present until the fetch finishes. As a result I am always redirected to the homepage instead of the page I refreshed on or typed. I tried setting a 'Loading' state but it only works for the App Component.
Example: I am on '/details/1234' I click refresh and I am sent back to '/'.
Is there any way to fix this behaviour? Maybe some changes in the router or forcing React to not do anything until that fetch is finished? Thanks in advance.
Here is the code for my provider:
import { createContext, useEffect, useState } from 'react'; export const AuthContext = createContext(); function AuthContextProvider(props) { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { async function initialUser() { try { const response = await fetch(`/api/users/profile`, { headers: { "Content-Type": "application/json" }, method: "GET", credentials: 'include' }); setLoading(false); const userData = await response.json(); return userData.message ? setUser(null) : setUser(userData) } catch (error) { console.log(error); } } if (!user) { initialUser(); } }, [user]); return ( <AuthContext.Provider value=> {props.children} </AuthContext.Provider> ) } export default AuthContextProvider
Here is the code for the App Component. The App Component is wrapped by the Provider and the Router in index.js
import { useContext } from 'react'; import { Switch, Route, Redirect } from 'react-router-dom'; import './App.css'; import { AuthContext } from './context/AuthContext'; import Navigation from './components/Navigation/Navigation'; import Footer from './components/Footer/Footer'; import Homescreen from './components/HomeScreen/HomeScreen'; import LandingScreen from './components/LandingScreen/LandingScreen'; import SignScreen from './components/SignScreen/SignScreen'; import Search from './components/Search/Search'; import Genres from './components/Genres/Genres'; import Details from './components/Details/Details'; import Watch from './components/Watch/Watch'; import Profile from './components/Profile/Profile'; function App() { const { user, loading } = useContext(AuthContext); return ( !loading ? <div className="App"> <Navigation user={user} /> <Switch> <Route exact path="/" render={() => (!user ? <LandingScreen /> : <Homescreen />)} /> <Route path="/sign-in" render={() => (!user ? <SignScreen /> : <Redirect to="/" />)} /> <Route path="/sign-up" render={() => (!user ? <SignScreen /> : <Redirect to="/" />)} /> <Route path="/profile" render={() => (!user ? <Redirect to="/sign-in" /> : <Profile />)} /> <Route path="/search" render={() => (!user ? <Redirect to="/sign-in" /> : <Search />)} /> <Route path="/movies/:genre" render={() => (!user ? <Redirect to="/sign-in" /> : <Genres />)} /> <Route path="/details/:id" render={() => (!user ? <Redirect to="/sign-in" /> : <Details />)} /> <Route path="/watch/:id" render={() => (!user ? <Redirect to="/sign-in" /> : <Watch />)} /> </Switch> <Footer /> </div> : null ); } export default App;
https://stackoverflow.com/questions/66847103/react-problem-with-router-before-fetching-the-user March 29, 2021 at 07:25AM
没有评论:
发表评论