Carla Agulló
Carla Agulló

Reputation: 35

Async problem at render time of React function: it will redirect directly instead of waiting for fetch to end

I want a page to render based on token validation. If the token is valid, it renders, if not, redirects. When I did this using a React Class there was no problem whatsoever and everything works as expected. Now, due to my need of using a param on the URL route (the token), I need to use Hooks. React Router constrains in this matter in order to use {useParams}. This has brought unexpected async problems. This is the code. If instead of doing a I render some regular it actually works fine, but I believe it is a lousy approach and would like to know the proper way to handle this so that it redirects if the token validation was incorrect and renders the right component if it was correct. Also, this is the first time I work with React fuctions instead of Components so any other tip for cleaner code will be appreciated.

import React, { useState } from 'react';
import {
    useParams, Redirect
} from "react-router-dom";


export default function ResetPassword() {

    let { token } = useParams();
    const [tokenStatus, setTokenStatus] = useState(false);

    const validateToken =  () => {
        var myHeaders = new Headers();
        myHeaders.append("access-token", token);

        var requestOptions = {
            method: 'POST',
            headers: myHeaders,
            redirect: 'follow'
        };

        fetch("http://localhost:4000/verifyemailtoken", requestOptions)
        .then(response => response.text())
        .then(result => {if (result==="Access Granted")
        {
                setTokenStatus(true);

        }})
        .catch(error => console.log('error', error));
    }

    validateToken();


    if (tokenStatus) {
        return (

            <div className="app">
                THE TOKEN WAS VALID       
            </div>
        )
    }
    else {

        return (
            <Redirect to="/home/>
 
        )
    }

}

Upvotes: 1

Views: 134

Answers (1)

goto
goto

Reputation: 4435

It sounds like what you need additional state which would indicate that the check is running prior to showing the the token was valid message or redirecting users to home.

function ResetPassword() {
  const { token } = useParams();
  const [tokenCheckComplete, setTokenCheckComplete] = React.useState(false);
  const [tokenStatus, setTokenStatus] = React.useState(false);
  
  React.useEffect(() => {
    var myHeaders = new Headers();
    myHeaders.append("access-token", token);

    var requestOptions = {
      method: "POST",
      headers: myHeaders,
      redirect: "follow"
    };
    
    // reset state when new token is passed
    setTokenStatus(false);
    setTokenCheckComplete(false);

    fetch("http://localhost:4000/verifyemailtoken", requestOptions)
      .then(response => response.text())
      .then(result => {
        if (result === "Access Granted") {
          setTokenStatus(true);
        }
        setTokenCheckComplete(true);
      })
      .catch(error => {
        setTokenStatus(false);
        setTokenCheckComplete(true);
      });
  }, [token]);

  if (!tokenCheckComplete) {
    return "Loading...";
  }

  return tokenStatus ? (
    <div className="app">THE TOKEN WAS VALID</div>
  ) : (
    <Redirect app="/home" />
  );
}

Upvotes: 2

Related Questions