'Unable to update a state while using fetch in reducer in React-Redux

I'm working on a react-redux project to learn authentication. I have a SignUp form where I post the details to google firebase from a reducer and update the responseStatus to true which is turn dispatches an action to update 'isLoggedIn' to true to enable few protected routes. The POST is successful and the response is proper, however, when I check the responseStatus from within the .then() while fetch(), I see the state updated, however outside the 'if' statement, I see that status is still the default one. I could feel that I'm getting this issue due to improper understanding of promises, but not exactly which part. Please let me know how do I resolve this?

Here is the code of SignUp form. I've removed few state updating lines of code, to show only the dispatching events and the states that I retrieve from reducers.

const SignUp = () => {
  const dispatch = useDispatch();
  
  const responseStatus = useSelector(
    (state) => state.DatabaseCommunicationReducer.responseStatus
  );
  console.log(responseStatus);

  const formSubmitHandler = (e) => {
    if (!isValidEmail || !isValidPassword || !isConfirmPassword) {
      dispatch({
        type: "TOGGLE_MODAL",
        payload: showModal,
      });
    } else {
      dispatch({
        type: "CREATE_ACCOUNT",
        payload: {
          enteredEmail,
          enteredPassword,
        },
      });
      if (responseStatus) {
        dispatch({
          type: "UPDATE_LOGGEDIN",
          payload: true,
        });
      }
    }
    e.preventDefault();
  };

The following are the codes of 2 reducers that updates the states. The first is the DatabaseCommunicationReducer which posts the user details to firebase.


const initialData = {
    token: "",
    responseStatus: false,
  };
  
  const DatabaseCommunicationReducer = (state = initialData, action) => {
    const url =
      "https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=[API_KEY]";
    if (action.type === "CREATE_ACCOUNT") {
      fetch(url, {
        method: "POST",
        body: JSON.stringify({
          email: action.payload.enteredEmail,
          password: action.payload.enteredPassword,
          returnSecureToken: true,
        }),
        headers: {
          "Content-Type": "application/json",
        },
      })
        .then((response) => {
          if (response.ok) {
            state.responseStatus = true;
            return response.json();
          }
        })
        .then((data) => {
          state.token = data.idToken;
          return {
            token: state.token,
            responseStatus: state.responseStatus,
          };
        });
    }
  
    return state;
  };
  
  export default DatabaseCommunicationReducer;

The responsesStatus returned inside the .then() is true while outside of fetch and inside of 'if' is the default one. Here is the issue according to my understanding.

Here is the code of reducer that updates the isLoggedIn

const initialState = {
  isLoggedIn: false,
  isLogin: false,
};

const LoginReducer = (state = initialState, action) => {
  if (action.type === "LOGIN_STATUS") {
    state.isLogin = !action.payload;
    return {
      isLoggedIn: state.isLoggedIn,
      isLogin: state.isLogin,
    };
  }

  if (action.type === "UPDATE_LOGGEDIN") {
    state.isLoggedIn = action.payload;
    return {
      isLoggedIn: state.isLoggedIn,
      isLogin: state.isLogin,
    };
  }
  return state;
};

export default LoginReducer;

Here is the code in Header component where I set the nav bar according to whether the user is logged in or not based on isLoggedIn

const Header = () => {
  const isLoggedIn = useSelector((state) => state.LoginReducer.isLoggedIn);
  console.log(isLoggedIn);

  return (
    <div className={styles.header}>
      <h1 className={styles.heading}>
        The <span className={styles.span}>Poke</span>World
      </h1>
      <ul>
        {isLoggedIn && (
          <li>
            <Link className={styles.link} to="/pokelist">
              PokeList
            </Link>
          </li>
        )}
        {isLoggedIn && (
          <li>
            <Link className={styles.link} to="/">
              Logout
            </Link>
          </li>
        )}
        {!isLoggedIn && (
          <li>
            <Link className={styles.link} to="/">
              Login/SignUp
            </Link>
          </li>
        )}
      </ul>
    </div>
  );
};

export default Header;

I hope I've shared what all are required to help you resolve my issue. Thanks in advance.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source