【问题标题】:React.useEffect: State not updating after axios requestReact.useEffect:在 axios 请求后状态未更新
【发布时间】:2020-07-05 04:44:09
【问题描述】:

我正在尝试将类组件转换为功能组件以利用React.useState hookReact.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。我还添加了规定的清理功能。

谁能提供任何见解为什么它根本不渲染,即成功,不同的错误结果?

【问题讨论】:

  • 我将您的组件写得更好一些,并将其作为另一个答案发布。另外,我为您的动机问题投了赞成票。希望第二个答案可以帮助您更好地编写组件并更具可读性。
  • 亲爱的安东尼奥,感谢您对我的支持。我想第一个答案更适合这篇文章。第二个只是描述干净的代码。第一个实际上,解释问题的原因。真的谢谢。如果对您有帮助,请查看我的个人资料并阅读我的简历。

标签: reactjs token react-hooks use-effect use-state


【解决方案1】:

您在异步调用后返回。所以你的状态肯定变成了{}

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

【讨论】:

  • 非常感谢!你能解释一下是什么让它变得嘈杂吗?
  • @AntonioPavicevac-Ortiz,请稍等,我正在探亲,会议结束后我会为您发送一个 CodeSandBox。
  • 当然,无论如何!期待与Antonio Pavicevac-Ortiz === 'better dev' 相同的见解
【解决方案2】:

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

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

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

  • 切勿将内容写入 JavaScript 逻辑代码。将其写入另一个文件并导入它。这意味着您应该分隔您的 URL 路径。就像分离 API 调用一样。

  • 上帝怜悯你,你为什么不用这份恩慈?我的意思是async/await。无疑它使所有代码更具可读性。

  • optional chainging 用于嵌套值,例如match.params.token

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

【讨论】:

  • 感谢 411 和很好的解释!哦,顺便说一句,当它是一个类 Component 时,组件声明和销毁是遗留在声明中的。
猜你喜欢
  • 2019-03-13
  • 2019-08-09
  • 1970-01-01
  • 1970-01-01
  • 2019-10-01
  • 2021-04-09
  • 1970-01-01
  • 2019-04-03
  • 1970-01-01
相关资源
最近更新 更多