【问题标题】:Wait for API call data before render react hooks在渲染反应钩子之前等待 API 调用数据
【发布时间】:2019-11-20 14:35:29
【问题描述】:

我进行 API 调用。

似乎 React 继续构建一个没有数据的表,从而引发了

的错误

Uncaught TypeError: Cannot read property 'map' of undefined

这就是我正在做的事情

useEffect() 很简单

  const [data, setData] = useState();
  const [isBusy, setBusy] = useState()

  useEffect(() => {
    setBusy(true);
    async function fetchData() {
      const url = `${
        process.env.REACT_APP_API_BASE
        }/api/v1/endpoint/`;

      axios.get(url).then((response: any) => {
        setBusy(false);
        setData(response.data.results)
        console.log(response.data.results);
      });
    }

    fetchData();
  }, [])

然后我尝试使用来自上述 API 调用的数据呈现一个表格(当它可用时)

            <div className="col-md-12 mt-5">
              {isBusy ? (
                <Loader />
              ) : (
                  <table className="table table-hover">
                    <thead>
                      <tr>
                        <th scope="col">Pharmacy User Full Name</th>
                        <th scope="col">Tests This Month</th>
                        <th scope="col">Tests This Week</th>
                        <th scope="col">Last Test Date</th>
                      </tr>
                    </thead>
                    <tbody>
                      {data.map((item: any, index: any) => {
                        return (<tr>
                          <th scope="row" key={index}>{item.name}</th>
                          <td>Mark</td>
                          <td>Otto</td>
                          <td>@mdo</td>
                        </tr>
                        )
                      })}

                    </tbody>
                  </table>
                )}
            </div>

上面的内容对我来说足够直观。所以不确定我需要做什么。谢谢。

【问题讨论】:

  • 你的 console.log 显示什么?
  • @Konstantin Uncaught (in promise) TypeError: Cannot read property 'map' of undefined
  • 我认为@Vencovsky 解决方案应该适合您。请记住,您可能需要先使用.json() 解析收到的结果

标签: reactjs react-hooks


【解决方案1】:

你应该在useState初始值中设置isBusy为true

//                            initial value
const [isBusy, setBusy] = useState(true)

还要在data.map之前检查data

// checking data
{data && data.map((item: any, index: any) => {
    return (<tr>
      <th scope="row" key={index}>{item.name}</th>
      <td>Mark</td>
      <td>Otto</td>
      <td>@mdo</td>
    </tr>
    )
})}

【讨论】:

  • 现在将两者结合起来。检查数据部分太重要了。也感谢您指出这一点。会记住的
  • @Vencovsky - 你能解释一下为什么我们要在 data.map 之前检查数据吗?是否确定数据是否存在?
  • @lAaravl 是因为data 可能是undefined,如果您在不检查数据是否真实的情况下执行data.map,您可能会收到错误消息,指出cannot read property map of undefined. You also might ask "How will data be undefined?" and the reason why it can be undefined is that the data` 状态被初始化为@ const [isBusy, setBusy] = useState() 中的 987654331@(useState 中的空参数正在传递 undefined 作为初始状态。
  • @lAaravl 更好的检查是Array.isArray(data) &amp;&amp; data.map(...),所以它只有在data 实际上是一个数组时才有效,但在这种情况下,只做data &amp;&amp; data.map(...) 也可以。
【解决方案2】:

useEffect 只会在组件尝试渲染后将isBusy 设置为true(为时已晚)。请记住,useEffect 仅在浏览器完成绘制后运行。所以isBusy 的第一个断言是undefined,其计算结果为false

true定义为isBusy的初始状态

const [isBusy, setBusy] = useState(true)

或者检查是否存在data 而不是isBusy

【讨论】:

  • 如果我们不使用 useState 而是使用 useEffect 并在渲染前等待 API 调用完成怎么办?
【解决方案3】:

您的setBusy(true); 发生在useEffect 中。 useEffect 将在您第一次渲染后执行,因此为时已晚。

我建议通过useState的参数将isBusy默认设置为true:

const [isBusy, setBusy] = useState(true);

然后,您不再需要在 useEffect 中将其设置为 true。

【讨论】:

    猜你喜欢
    • 2021-04-27
    • 1970-01-01
    • 2021-01-06
    • 2020-12-24
    • 2019-12-31
    • 2021-04-05
    • 2021-08-23
    • 2016-04-30
    • 1970-01-01
    相关资源
    最近更新 更多