在渲染react-hooks之前等待 API 调用数据

IT技术 reactjs react-hooks
2021-05-17 17:06:53

我进行了 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>

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

3个回答

您应该isBusyuseState初始值中设置为 true

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

还要检查data之前data.map

// 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>
    )
})}

useEffect只会在组件尝试渲染(为时已晚)后设置isBusytrue请记住,useEffect只有在浏览器完成绘制后才会运行。所以第一个断言isBusyundefinedwhich 评估为false

定义true为初始状态isBusy

const [isBusy, setBusy] = useState(true)

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

setBusy(true);发生在useEffect. useEffect后你的第一个呈现,所以这是为时已晚将执行。

我建议isBusy通过以下参数默认设置为 true useState

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

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