Search code examples
reactjstokenreact-hooksuse-effectuse-state

React.useEffect: State not updating after axios request


I am in the process of trying to convert a class Component into a functional component to leverage the React.useState hook and React.useEffect hook. The component is making requests to check if a token exists on a server.

import React, { Component } from 'react';

import { Loader, Dimmer, Transition, Message } from 'semantic-ui-react';
import axios from 'axios';

import { hasBeenVerified } from '../../store/reducers/users/index';

import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';


function Confirmation({ match, isAccountVerified, hasBeenVerified }) {
  var [token, setToken] = React.useState(null);
  var [duration, setDuration] = React.useState(500);
  var [responseMessage, setResponseMessage] = React.useState({});
  var [error, setError] = React.useState(false);

  React.useEffect(() => {
    console.log('token ', token);
    axios
      .get(`http://localhost:8016/users/confirmation/${setToken(match.params.token)}`)
      .then(response => {
        if (response.status === 200) {
          hasBeenVerified();
          setResponseMessage(response.data.msg);
          return;
        }
      })
      .catch(function(error) {
        if (error.response.status === 404) {
          setResponseMessage(error.response.data.msg);
          setError(true);
          return;
        }
        if (error.response.status === 400) {
          setResponseMessage(error.response.data.msg);
          setError(true);
          return;
        }
      });

      return () => {
       setToken(null);
       setResponseMessage({});
       setError(false);
    };
  }, [token, isAccountVerified, hasBeenVerified, setResponseMessage, setError]);
  console.log('token ', token);

  console.log('isAccountVerified ', isAccountVerified);
  console.log('match', match);
  console.log('responseMessage', responseMessage);
  return (
    <div className="login-form">
      <Transition
        visible={isAccountVerified}
        unmountOnHide={true}
        animation="scale"
        duration={duration}
      >
        {!isAccountVerified ? (
          <Dimmer active inverted>
            <Loader />
          </Dimmer>
        ) : (
          <Message success={!error} error={error} header={responseMessage[0]} />
        )}
      </Transition>
    </div>
  );
}

function mapStateToProps(state) {
  const { users } = state;
  const { isAccountVerified } = users;

  return { isAccountVerified };
}

const mapDispatchToProps = dispatch => bindActionCreators({ hasBeenVerified }, dispatch);

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Confirmation);

I have added values to the dependency array because it is an outside value it depends on. I've also added the cleanup function prescribed as well.

Can anyone offer any insight why it doesn't render at all i.e. success, the different error results?


Solution

  • You return after an asynchronous call. so definitely your state became {}.

    Change the [token, isAccountVerified, hasBeenVerified, setResponseMessage, setError] to [] and it works well.

    This array is using for running the useEffect callback function for changing the values of it. you passed the functions?!

    Even you destruct the Component but never use it. your code is very very noisy to read.

    import React, { useState, useEffect } from 'react';
    
    ~~~
    
    useEffect(() => {
        console.log('token ', token);
        axios.get('http://localhost:8016/users/confirmation/${setToken(match.params.token)}')
          .then(response => {
            if (response.status === 200) {
              hasBeenVerified();
              setResponseMessage(response.data.msg);
              // return;
            }
          })
          .catch(function(error) {
            if (error.response.status === 404) {
              setResponseMessage(error.response.data.msg);
              setError(true);
              // return;
            }
            if (error.response.status === 400) {
              setResponseMessage(error.response.data.msg);
              setError(true);
              // return;
            }
          });
    
          /* return () => { // this commented part run exactly after asynchronous axios call. you don't need this part.
           setToken(null);
           setResponseMessage({});
           setError(false);
        }; */ 
      }, []);