Arturo
Arturo

Reputation: 17

called async function from state is not waiting (react)

I call a state function in my component, the function should change the state(and it does but late), i want to log the change but the log triggers before the state is changed this is the function in the state:

const login = async (user, password) => {
    const body = {
      username: user,
      password: password,
    };
    await axios
      .post('/sessions', body, {
        headers: { 'Content-Type': 'application/json' },
      })
      .then((resp) => {
        dispatch({ type: LOGIN, payload: resp.data.data });
      })
      .catch((err) => {
        console.log(err.response.data);
      });
  };

and this is the call in the component

  const onSubmit = (e) => {
    e.preventDefault();
    login(user, password);
    console.log(credes);
  };

"credes" is the state for that response, but it keeps printing the initial state witch is an empty object the function triggers on the form submission but logs first and updates the state later.

Upvotes: 1

Views: 85

Answers (2)

Arturo
Arturo

Reputation: 17

As pointed out by bubulledu93, ronakvp and coreyward, I was butchering the syntax. I was trying to perform two actions in one function, so I moved the log into a useEffect to watch for changes in the "credes" hope is the right way but is working as I needed it.

  const login = (user, password) => {
    const body = {
      username: user,
      password: password,
    };
    axios
      .post('/sessions', body, {
        headers: { 'Content-Type': 'application/json' },
      })
      .then((resp) => {
        dispatch({ type: LOGIN, payload: resp.data });
      })
      .catch((err) => {
        console.log(err.response.data);
      });
  };

and the call in the component + the useEffect

  const onSubmit = (e) => {
    e.preventDefault();
    login(user, password);
  };

  useEffect(() => {
    if (credes.success) {
      console.log(credes.data);
    }
  }, [credes]);

Upvotes: 1

coreyward
coreyward

Reputation: 80041

There isn't any benefit to awaiting as the last call in a function. Instead of using async and await, simply return the Promise chain started by axios.post() to onSubmit and then chain on it (or use await there):

  const login = (user, password) => {
    const body = {
      username: user,
      password: password,
    };
    return axios
      .post('/sessions', body, {
        headers: { 'Content-Type': 'application/json' },
      })
      .then((resp) => {
        dispatch({ type: LOGIN, payload: resp.data.data });
      })
      .catch((err) => {
        console.log(err.response.data);
      });
  };

  // Option 1:
  const onSubmit = (e) => {
    e.preventDefault();
    login(user, password)
      .then(() => {
        console.log(credes);
      });
  };

  // Option 2:
  const onSubmit = async (e) => {
    e.preventDefault();
    await login(user, password);
    console.log(credes)
  }

Upvotes: 0

Related Questions