1

Can someone explain why "condition" is not triggering re-render when it is changed when the response is received and state is set?

When this code is run, it always redirects to "/unauthorized/login" even when the response is true. I thought page is always re-rendered when the state is changed.

const PrivateRoute = props => {
const [condition, setCondition] = useState('');

useEffect(() => {
    if (!condition) {
        getUserAccess();
    }
}, [condition]);

const getUserAccess = async () => {
    const response = await axios.get("/some-api");
    const status = response.data; /* status will either be true or false */
    setCondition(status);
}

return condition ? (<Route path={props.path} exact={props.exact} component={props.component}/>) :
    (<Redirect to="/unauthorized/login"/>); 
};

export default PrivateRoute;
4
  • 2
    Is the condition state updated to a truthy value? What is the value of status? Commented Aug 27, 2021 at 5:45
  • 1
    Why do you set empty string in initial data in useState()? It must be false or true for conditional Commented Aug 27, 2021 at 5:45
  • 1
    @Danial Falsey values are also ok to use in boolean expressions. Commented Aug 27, 2021 at 5:47
  • The value of status will either be true or false. I have updated the question to make it clear. Commented Aug 27, 2021 at 5:52

3 Answers 3

3

You should/could use a third "pending" state that is neither explicitly true or false, and wait for the GET request to resolve. Without this the private route component doesn't wait for the resolved state and uses the falsey ('') initial condition state and renders the redirect.

const PrivateRoute = props => {
  const [condition, setCondition] = useState(null);

  useEffect(() => {
    if (!condition) {
      getUserAccess();
    }
  }, [condition]);

  const getUserAccess = async () => {
    try {
      const response = await axios.get("/some-api");
      setCondition(response.data);
    } catch(err) {
      // handle any error logging, etc..
      setCondition(false); // clear "loading state" so redirect can happen
    }
  }

  if (condition === null) {
    return <Spinner />; // or any other "pending" UI indication
  }

  return condition ? (
    <Route {...props} />
  ) : (
    <Redirect to="/unauthorized/login"/>
  );
};
Sign up to request clarification or add additional context in comments.

Comments

1

It's because your condition is !'' = false in the initial render.

So it's always got to your 2nd condition: <Redirect to="/unauthorized/login"/> without having a chance for useEffect to run.

To solve this, you will need to have a loading indicator to let your component know that you are waiting for the response:

Something like this:

const PrivateRoute = props => {
const [condition, setCondition] = useState('');
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
    if (!condition) {
        getUserAccess();
    }
}, [condition]);

const getUserAccess = async () => {
    const response = await axios.get("/some-api");
    const status = response.data; /* status will either be true or false */
    setCondition(status);
    setIsLoading(false);
}

if (isLoading) return <h1>Loading...</h1>;

return condition ? (<Route path={props.path} exact={props.exact} component={props.component}/>) :
    (<Redirect to="/unauthorized/login"/>); 
};

export default PrivateRoute;

Comments

0

Axios is promise based library

const [condition, setCondition] = useState(false);

useEffect(() => {
        if (!condition) {
            axios.get("https://jsonplaceholder.typicode.com/posts/1")
            .then( (response) =>{
                //console.log(response.data)
                setCondition(response.data)
            })
            .catch(
                (error)=>{
                    console.log(error);
                }
            )
        }
    }, [condition]);

2 Comments

Condition is still initially false and the redirect will be rendered. You've only converted async/await to a Promise chain. You are correct though that any errors or rejected promises should probably be caught.
Tq for pointing me, i think catch block holds all the stuff you raised, but my main concern is to setCondition()

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.