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