Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

useState in useEffect does not update state

I'm new to React Hooks and using react 16.13.1.

I'm going to implement Auth component which enables to handle logging in.

But it does not seem update the state currentUser properly, even though setCurrentUser is called with response Object.

What is wrong with this code?

import React, { useState, useEffect } from "react";
import { Route, Redirect } from "react-router-dom";
import { checkLoggedIn } from "utils/Api";

export const Auth = (props) => {
  const [currentUser, setCurrentUser] = useState(null);
  const [isLoading, setIsLoading] = useState(false);
  console.log(currentUser);

  useEffect(() => {
    const f = async () => {
      setIsLoading(true);
      console.log(isLoading);
      const res = await checkLoggedIn();
      if (!!res) { // ==> true
        setCurrentUser(res);
        console.log(currentUser); // ==> null!
      }
      setIsLoading(false);
    };
    f();
  });

  if (isLoading) {
    return <div>loading</div>;
  }

  console.log(currentUser); // ==> null!
  return !!currentUser ? (
    <Route children={props.children} />
  ) : (
    <Redirect to={"/login"} />
  );
};
like image 767
Taichi Avatar asked Feb 04 '26 20:02

Taichi


1 Answers

setCurrentUser updates the state asynchronously, so you can't use currentUser immediately afterwards.

However, you can use another useEffect to know when the state was changed:

useEffect(() => {
  // currentUser changed
}, [currentUser])

I also noticed that you are not passing an empty array to the useEffect you already have, so it will trigger everytime the component is updated. If you need to execute your useEffect only once you have to pass an empty array as a second argument, like this:

  useEffect(() => {
    const f = async () => {
      // ...
    };
    f();
  }, []);
like image 77
germanescobar Avatar answered Feb 06 '26 14:02

germanescobar