【问题标题】:react promise in functional component with UseEffect and UseState doesn't work使用 UseEffect 和 UseState 对功能组件中的承诺做出反应
【发布时间】:2020-12-04 11:21:33
【问题描述】:

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

我的问题是我想通过 axios async/await 在单独的文件中完成数据获取,以提高应用程序的可扩展性,但是我不明白如何更新状态以防承诺得到解决(不是被拒绝)。

特别是我试图从 promise 中检索一个名为 data in state 的表行数组,但我不知道如何在 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");
 }
};

在上图中可以看到action.js中调用的promise response里面的rows数组是存在的。

不幸的是,这段代码不起作用,错误:Uncaught (in promise) TypeError: Cannot read property 'forEach' of undefined

我找到了另一种解决方案,即在 useEffect 方法中定义承诺,如下所示:

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

fetchData();
}, []);

此代码在我的应用程序中运行,但正如我所说,我不喜欢在组件文件中包含承诺,而是希望它们在 action.js 中为应用程序可扩展性提供所有承诺(以防 url 更改我不'不必更改所有文件)但在这种情况下,我不知道将 setData(result.data.rows); 放在哪里,这在最后一个示例中似乎是正确的选择

有什么建议吗? 谢谢

【问题讨论】:

  • 你仍然需要使用 async/await。 .then() 在返回值时执行,但是您的函数将继续渲染并且不会等待它。 (通过尝试在 null 状态下访问 forEach 导致它出错)

标签: reactjs promise use-effect use-state


【解决方案1】:

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

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
}

【讨论】:

  • 在您的解决方案中添加了 async /await,但我仍然收到错误:Uncaught TypeError: Cannot read property 'forEach' of undefined
  • 并加上一个警告:react-dom.development.js:88 警告:效果函数不能返回除用于清理的函数之外的任何内容。看起来你写了 useEffect(async () => ...) 或返回了一个 Promise。相反,在你的效果中编写异步函数并立即调用它: useEffect(() => { async function fetchData() { // 你可以在这里等待 const response = await MyAPI.getData(someId); // ... } fetchData(); }, [someId]); // 如果效果不需要道具或状态,则为 []
  • 更新了我的答案以修复警告(道歉)。在执行 Data.forEach 之前尝试使用 null 检查。在返回中,您可以使用 {Data != null ? (
    ) : null } 仅在有效时才渲染它,否则什么都没有。
  • 也许你可以有let data = await props.getTableRows(id)setData(data)
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2020-12-14
    • 2021-02-28
    • 1970-01-01
    • 2020-10-20
    • 1970-01-01
    • 2019-09-23
    • 2020-05-23
    • 2021-11-26
    • 2020-07-26
    相关资源
    最近更新 更多