在 React 功能组件中使用 async/await

新手上路,请多包涵

我刚刚开始将 React 用于一个项目,并且真的很难将 async/await 功能合并到我的一个组件中。

我有一个名为 fetchKey 的异步函数,它从我通过 AWS API 网关提供服务的 API 获取访问密钥:

 const fetchKey = async authProps => {
  try {
    const headers = {
      Authorization: authProps.idToken // using Cognito authorizer
    };

    const response = await axios.post(
      "https://MY_ENDPOINT.execute-api.us-east-1.amazonaws.com/v1/",
      API_GATEWAY_POST_PAYLOAD_TEMPLATE,
      {
        headers: headers
      }
    );
      return response.data.access_token;

  } catch (e) {
    console.log(`Axios request failed! : ${e}`);
    return e;
  }
};

我正在使用 React 的 Material UI 主题,并且想使用它的仪表板模板之一。不幸的是,仪表板模板使用功能性无状态组件:

 const Dashboard = props => {
  const classes = useStyles();

  const token = fetchKey(props.auth);
  console.log(token);

  return (
  ... rest of the functional component's code

我的 console.log(token) 的结果是一个 Promise,这是意料之中的,但我的 Google Chrome 浏览器中的屏幕截图有些矛盾 - 它是待定的,还是已解决? 在此处输入图像描述

其次,如果我改为尝试 token.then((data, error)=> console.log(data, error)) ,我会得到 undefined 这两个变量。这似乎表明该功能尚未完成,因此尚未解析 dataerror 的任何值。但是,如果我尝试放置一个

const Dashboard = async props => {
  const classes = useStyles();

  const token = await fetchKey(props.auth);

React 强烈抱怨:

 > react-dom.development.js:57 Uncaught Invariant Violation: Objects are
> not valid as a React child (found: [object Promise]). If you meant to
> render a collection of children, use an array instead.
>     in Dashboard (at App.js:89)
>     in Route (at App.js:86)
>     in Switch (at App.js:80)
>     in div (at App.js:78)
>     in Router (created by BrowserRouter)
>     in BrowserRouter (at App.js:77)
>     in div (at App.js:76)
>     in ThemeProvider (at App.js:75)

现在,我将第一个声明我没有足够的经验来理解这个错误消息是怎么回事。如果这是一个传统的 React 类组件,我会使用 this.setState 方法来设置一些状态,然后继续我的快乐之路。但是,我在这个功能组件中没有那个选项。

如何将异步/等待逻辑合并到我的功能性 React 组件中?

编辑: 所以我只想说我是个白痴。返回的实际响应对象不是 response.data.access_token 。它是 response.data.Item.access_token 。呸!这就是为什么结果返回为未定义的原因,即使实际承诺已解决。

原文由 Yu Chen 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
2 个回答

你必须确保两件事

  • useEffect is similar to componentDidMount and componentDidUpdate , so if you use setState here then you need to restrict the code execution at some point when用作 componentDidUpdate 如下图:
 function Dashboard() {
  const [token, setToken] = useState('');

  useEffect(() => {
    // React advises to declare the async function directly inside useEffect
    async function getToken() {
      const headers = {
        Authorization: authProps.idToken // using Cognito authorizer
      };
      const response = await axios.post(
        "https://MY_ENDPOINT.execute-api.us-east-1.amazonaws.com/v1/",
        API_GATEWAY_POST_PAYLOAD_TEMPLATE,
        { headers }
      );
      const data = await response.json();
      setToken(data.access_token);
    };

    // You need to restrict it at some point
    // This is just dummy code and should be replaced by actual
    if (!token) {
        getToken();
    }
  }, []);

  return (
    ... rest of the functional component's code
  );
}

原文由 Milind Agrawal 发布,翻译遵循 CC BY-SA 4.0 许可协议

使用 React Hooks,您现在可以在功能组件中实现与 Class 组件相同的功能。

 import { useState, useEffect } from 'react';

const Dashboard = props => {
  const classes = useStyles();
  const [token, setToken] = useState(null);
  useEffect(() => {
     async function getToken() {
         const token = await fetchKey(props.auth);
         setToken(token);
     }
     getToken();
  }, [])

  return (
  ... rest of the functional component's code
  // Remember to handle the first render when token is null

也看看这个: Using Async await in react component

原文由 Tan Dat 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏