React.useEffect: axios 请求后状态未更新

React.useEffect: State not updating after axios request

我正在尝试将 class 组件转换为功能组件以利用 React.useState hook and React.useEffect hook。该组件正在请求检查服务器上是否存在令牌。

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);

我已经添加了values to the dependency array because it is an outside value it depends on。我还添加了规定的清理功能。

任何人都可以提供任何见解,为什么它根本不呈现,即成功,不同的错误结果?

你return在一个异步调用之后。所以你的状态肯定变成了 {}.

[token, isAccountVerified, hasBeenVerified, setResponseMessage, setError] 更改为 [],效果很好。

此数组使用 运行 useEffect 回调函数来更改它的值。你通过了功能?!

即使你破坏了 Component 但永远不会使用它。你的代码读起来非常嘈杂。

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);
    }; */ 
  }, []);

下面我写了一个通用的ReactJS代码,基于Airbnb ESLint标准

  • 我不明白为什么要使用解构赋值导入 Component。它是一个函数组件,所以只需通过解构赋值导入useStateuseEffect

  • 为什么要在组件内部调用 API。这不是一种常见的方式,将它写在另一个文件中并导入它或使用 redux 动作调度来调用你的 API 并从你的 redux 中获取你的 API 数据。这两种方式都很常见。

  • 切勿将您的内容写在 JavaScript 逻辑代码中。将它写在另一个文件中并导入它。这意味着您应该分隔您的 URL 路径。就像分开你的 API 电话一样。

  • 天道慈悲,你为何不用此恩情?我的意思是 async/await。毫无疑问,它使所有代码更具可读性。

  • match.params.token.

  • 等嵌套值使用 optional chainging
import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { Loader, Dimmer, Transition, Message } from 'semantic-ui-react';
import { hasBeenVerified } from '../../store/reducers/users';
import { confirmCall } from '[pathTo]/api'; // pseudo code

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

  useEffect(async () => {
    try {
      const response = await confirmCall(match?.param?.token);
      if (response.status === 200) {
        hasBeenVerified();
        setResponseMessage(response.data.msg);
      }
    } catch (error) {
      if (error.response.status === 404) {
        setResponseMessage(error.response.data.msg);
        setError(true);
      }
      if (error.response.status === 400) {
        setResponseMessage(error.response.data.msg);
        setError(true);
      }
    }
  }, []);


  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>
  );
}

const mapStateToProps = ({ users: { isAccountVerified } }) => ({
  isAccountVerified
});

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

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