使用UseEffect和UseState在功能组件中反应诺言

时间:2020-08-14 14:44:29

标签: reactjs promise use-effect use-state

我在获取数据并将其设置为使用useEffect和useState的功能组件中的状态时遇到问题。

我的问题是我想将axios async / await的数据提取保存在一个单独的文件中,以提高应用程序的可伸缩性,但是在不解决诺言的情况下,我不了解如何更新状态(不被拒绝) )。

特别是我正在尝试从Promise中检索状态为data的表行数组,但是我不知道如何将响应的结果设置为State

这是组件文件中的代码:

const [data, setData] = React.useState([]);
useEffect(() => {
   const { id } = props.match.params;
   props.getTableRows(id).then((res) => {
     setData(res);
   });
   //or is it better:
   //props.getTableRows(id).then(setData);  ?
}, []);

和我的action.js:

export const getTableRows = (id, history) => async (dispatch) => {
  try {
    const res = await axios.get(`/api/test/${id}`);
    dispatch({
      type: GET_TEST,
      payload: res.data.rows,
    });
 } catch (error) {
    history.push("/test");
 }
};

enter image description here 在上图中,可以看到在action.js中调用的promise响应中存在rows数组。

不幸的是,此代码无法正常工作,错误:未捕获(承诺)TypeError:无法读取未定义的属性'forEach'

我发现了另一个解决方案,它是在useEffect方法中定义promise,如下所示:

useEffect(() => {
   const { id } = props.match.params;
   const fetchData = async () => {
       const result = await axios.get(`/api/test/${id}`);
       setData(result.data.rows);
   };

fetchData();
}, []);

此代码在我的应用程序中有效,但是正如我说的那样,我不希望在组件文件中包含promise,而是希望将所有promise都放在action.js中以实现应用程序可伸缩性(以防我更改URL不必更改所有文件),但在那种情况下,我不知道将 setData(result.data.rows); 放在哪里

有什么建议吗? 谢谢

2 个答案:

答案 0 :(得分:0)

您仍然需要使用async / await。 .then()在返回值时执行,但是您的函数将继续渲染并且不会等待它。 (通过尝试以空状态访问forEach,从而使我们错误)。错误后,通过.then()的promise将更新值,这就是为什么您可以在控制台中看到它们的原因。

useEffect(() => {
  async function getData() {
      const { id } = props.match.params;
      await props.getTableRows(id).then((res) => {
       setData(res);
      });
  }
  getData()
}, []);

此外,在访问状态之前,您可以检查空值(通常是好的做法)。

if (this.state.somestate != null) {
//Run code using this.state.somestate
}

答案 1 :(得分:0)

我看不到您从getTableRows返回任何内容。您只是分派结果,但没有为函数调用返回res。 如果您提供了错误跟踪信息,将会很有帮助。