0

I am quite new to javascript and I have this issue. The return part doesn´t wait for my status from fetch. How can I make this happen ? I also tried to add some timeouts but that didnt work as well.

const LoggedRoute = ({ component: Component, ...rest}) => {
    const token = cookie.get('token');



    fetch(`${constants.urls.put}/auth/user`, {
        method: 'GET',
        headers:{'Authorization': 'Token ' + token}
    })
    .then(
        data => {
            data.json();
            status = data.statusText;
        }
        
    )


    return (
        <Route
        {...rest}
        render={props =>
        ((status != "OK")) ? (
            <Component {...props} />
        ) : (
            <Redirect
            to={{
                pathname: "/",
                state: { from: props.location}
            }}
            /> 
        )
}
/>
);

}
export default LoggedRoute
plosnak2
  • 3
  • 3
  • The first duplicate is the general explanation about the problem you are having. The second is a React-specific approach to solving it. – Quentin Aug 02 '20 at 14:54

1 Answers1

0

The easy way to handle this simple case is to return a <Loader /> or something like that while your fetch is running :

if(!fetchFinished) return <Loader />;

return (
// ...your code
);

You should also put your fetch in a useEffect hooks, and by doing that you could use the async...await pattern to wait for your fetch to end:

useEffect(async () => {
  const data = await fetch(...);
  const json = await data.json();
  // etc.

});

return (
  //... your code
);

the first solution mixed with your code would looks like that :

const LoggedRoute = ({ component: Component, ...rest }) => {
  const token = cookie.get('token');
  // Set a boolean to update when your query is done
  const [isFetchFinished, setIsFetchFinished] = useState(false);

  useEffect(() => {
    fetch(`${constants.urls.put}/auth/user`, {
      method: 'GET',
      headers: { Authorization: 'Token ' + token },
    }).then((data) => {
      data.json();
      status = data.statusText;
      // when you're finished with your data, set your boolean to true
      setIsFetchFinished(true);
    }, []); // Don't forget the empty deps array to make it act like 'componentDidMount'
  });

  if(!isFetchFinished) return <Loader />;

  return (
    <Route
      {...rest}
      render={(props) =>
        status != 'OK' ? (
          <Component {...props} />
        ) : (
          <Redirect
            to={{
              pathname: '/',
              state: { from: props.location },
            }}
          />
        )
      }
    />
  );
};
export default LoggedRoute;

Quentin Grisel
  • 4,794
  • 1
  • 10
  • 15
  • Could you please show me in my code, hat exactly do you think ? I am not sure how to check if the fetch already finished in your if statement – plosnak2 Aug 02 '20 at 15:06
  • @plosnak2 I edited my answers to show you what it would look like. You should also check the links added to tag your question as 'already answered', it will be useful. – Quentin Grisel Aug 02 '20 at 15:34
  • thanks a lot ! and one last thing, my program says that useState is not defined. Where can i define this ? If you could help me out with this on DC it would be really great. – plosnak2 Aug 02 '20 at 15:47
  • also useEffect functions seems like a problem. Is it a problem that its not a class? – plosnak2 Aug 02 '20 at 15:49
  • Of course you need to import it, or call it like `React.useState` (same for useEffect). It's a hook, you should read the chapter about it in the documentation https://reactjs.org/docs/hooks-intro.html – Quentin Grisel Aug 02 '20 at 16:05