reactjsreact-routermetronic

How to handle conditional redirect in react app routes?


I am using a metronic theme for my react project and now I am trying to do a conditional redirect based on value from an api. I found a file called Routes.js already written and I am trying to change there. This is what it looks like

 const [request, setRequest] = useState();
 const [isUserActive, setIsUserActive] = useState(false);

  useEffect(() => {
    fetch("http://82 ...")
      .then((res) => res.json())
      .then((data) => setRequest(data));
  }, []);

  useEffect(() => {
    if (request) {
      request.isUser=== true
        ? setIsUserActive(true)
        : setIsUserActive(false);
    }
  }, [request]);

  return (
    <Switch>
      <Route path="/error" component={ErrorsPage} />

      {!isUserActive ? (
        <Redirect to="error/error-v1" />
      ) : (
        <>
          <Redirect to="/" />
          <Layout>
            <BasePage />
          </Layout>
        </>
      )}
    </Switch>
  );

When isUserActive is true, I want to go to root path but if it isn't, I want to go to error page. isUserActive now logs

false 
false 
true

But my project is always redirecting to /error/error-v1 even though the final value is true, am I missing something here ?


Solution

  • You probably want to add another state for loading. The reason why is that with the current setup, once the code directs you to the /error endpoint there is no going back and it will always render the error page.

    const [request, setRequest] = useState();
    // vvv this was added vvv
    // vvv this was added vvv
    // vvv this was added vvv
    const [requestLoading, setRequestLoading] = useState(true);
    const [isUserActive, setIsUserActive] = useState(false);
    
     useEffect(() => {
       fetch("http://82 ...")
         .then((res) => res.json())
         .then((data) => setRequest(data));
     }, []);
    
     useEffect(() => {
       if (request) {
         // vvv this was added vvv
         // vvv this was added vvv
         // vvv this was added vvv
         setRequestLoading(false);
         request.isUser=== true
           ? setIsUserActive(true)
           : setIsUserActive(false);
       }
     }, [request]);
    
     return (
       // vvv this conditional rendering was added vvv
       // vvv this conditional rendering was added vvv
       // vvv this conditional rendering was added vvv
       {!requestLoading ? <Switch>
         <Route path="/error" component={ErrorsPage} />
    
         {!isUserActive ? (
           <Redirect to="error/error-v1" />
         ) : (
           <>
             <Redirect to="/" />
             <Layout>
               <BasePage />
             </Layout>
           </>
         )}
       </Switch> : <div />}
     );
    

    For now all this does is render a div if the request is still loading, then it routes you based on the result once its finished