0

My problem is that React will check first Routing for my page and afterwards is going to run useEffect() function. This gives me kind of a problem. What im doing is that i need useEffect() to run first in order to fetch data from local storage. That specific data "decides" in which page my application will redirect.

So that's the main App.js

function App() {

  const [user, setUser] = useState({id:null,authorized:false});

  useEffect(() => {
    const aUser = JSON.parse(localStorage.getItem("user"));
    if(aUser!=null){
      console.log(JSON.stringify(aUser));
      setUser(aUser);
    }
   
  }, [])

  return (
    <div className="App">
      <BrowserRouter>

          <Route exact path="/" render={ () => 
            !user.authorized ? <Login setUser={setUser} user={user}/> 
            : <Redirect to="/home" />  }
                />

          <Route exact path="/login" render={ () =>
             !user.authorized ? <Login setUser={setUser} user={user}/> 
              : null}/>

          <Route exact path="/home" 
            render={() => !user.authorized ?
              <Redirect to="/login" /> : <Forbidden/>
            }/>
      
        </BrowserRouter>
    </div>
  );
}

export default App;

So let's assume that user data is already stored in local storage and the user is authorized. When i start up my react app it will first show the Home page and that's because i have set the Route "/" to redirect to "/home" if the user is authorized. Ok that good. My "problem" is when i refresh the page from /home it will redirect to /login. Why? Because Routes will be checked first and after that the useEffect() will run.

An obvious solution will be to redirect to /home as i do for the first Route ("/"). OK i get that but why useEffect() Won't run first? That's my main question.

Update:

I can solve MY problem from the beginning but i want to know if there is a solution regarding useEffect(). One solution is as i said before to redirect to "/home" if user is authorized like that

<Route exact path="/login" render={ () =>
             !user.authorized ? <Login setUser={setUser} user={user}/> 
              : <Redirect to="/home" /> 
       }
    />

Basically the same code as "/" Route.

Another solution that may be the best it's to get rid of useEffect() and load the user data with useState() like this:

const [user, setUser] = useState(()=>localStorage.getItem("user"));
4
  • You could add a state property to see if it's loading or it's done, if it's loading show null otherwise show a component. Commented Dec 29, 2020 at 13:41
  • What happens if you add to the dependency array: [aUser] ? Commented Dec 29, 2020 at 13:45
  • daveceddia.com/react-hook-after-render/…. Commented Dec 29, 2020 at 13:51
  • @Magofoco it sets the user variable from local storage. It's the same "object" but i load it from the local storage. After the setUser() occurs, user.authorized is true. But the setUser() will run after the page has gone to /login route Commented Dec 29, 2020 at 13:52

1 Answer 1

3

The way you can solve this problem is by initializing the state itself by fetching from local storage like this:

 const [user, setUser] = useState(()=>localStorage.getItem("user"));

useState takes a function that can be used to initialize the state. This is used for lazy intialization.

Link to Docs

It's also good to keep in mind the order in which the different lifecycle hooks run.

Sign up to request clarification or add additional context in comments.

2 Comments

It's maybe the best solution but im gonna leave it unanswered. cause i wanna know if there is a solution with useEffect(). It may be helpful for others
Hi, I think its important to keep in mind the hooks flow diagram github.com/donavon/hook-flow. useEffect is the last hook to run after the browser has already been painted which is why you are facing the issue. The lazy initializer is the first hook to run. Good to see alternate solutions though

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.