Wait for API call data before render react hooks

ぃ、小莉子 提交于 2020-12-12 05:12:46

问题


I make an API call.

It appears React goes ahead to build a table without the data, thus throwing error of

Uncaught TypeError: Cannot read property 'map' of undefined

Here's what I'm doing

useEffect() pretty straightforward

  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();
  }, [])

Then I'm trying to render a table using the data from the API call above (as and when it becomes available)

            <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>

The above appears intuitive enough for me. So not sure what I need to do. Thanks.


回答1:


You should set isBusy to true in the useState initial value

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

And also check data before 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>
    )
})}



回答2:


useEffect will only set isBusy to true after the component tries to render(too late). Remember that useEffect only runs after the browser finishes painting. So the first assertion of isBusy is undefined which evaluates to false

Define true as initial state of isBusy

const [isBusy, setBusy] = useState(true)

Or check for the existence of data instead of isBusy




回答3:


Your setBusy(true); happens inside the useEffect. The useEffect will execute after your first render so this is too late.

I recommend setting isBusy to true by default via the parameter of useState:

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

You then don't need to set it to true inside the useEffect anymore.



来源:https://stackoverflow.com/questions/58956828/wait-for-api-call-data-before-render-react-hooks

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!