I'm trying to make a program that waits for array to be filled and then passes it to setData()
function. The data must be rendered after. But for some reasons react doesn't renders it, despite the fact that array is full, as i can see from console.
import { useEffect, useState } from 'react';
export default function EntitiesRecognized(props) {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
const call_razor = async (sentence) => {
try {
return new Promise((resolve, reject) => {
setTimeout(() => {resolve('200' sentence)}, 2000)
})
} catch (err) {
console.log(err)
}
}
useEffect(() => {
const dataFetch = async () => {
let arr = [];
await props.props.map(async prop => {
console.log(prop)
await call_razor(prop).then(response => arr.push(response))
});
setData(arr);
setLoading(false);
};
dataFetch();
}, []);
return (
<div>
{isLoading
? <h1>Loading</h1>
: data.map((sentence, idx) => {
return <h5 key={idx}>{sentence}<hr/></h5>
})
}
</div>
);
};
It shows no errors, just an empty page.
CodePudding user response:
await props.props.map(async prop => {
.map
returns an array, not a promise, so await
ing it does nothing. So you move past this line almost immediately, and then call setData
with an array that is still empty. React renders that empty array, and so nothing is put on the screen. Later, you mutate the array to contain stuff, but react doesn't know that you did this and won't rerender unless you set state again.
I recommend you make an array of promises, then use Promise.all to combine them into one promise, and then await
that to get the finished array:
const dataFetch = async () => {
const promises = props.props.map(prop => call_razor(prop))
const arr = await Promise.all(promises);
setData(arr);
setLoading(false);
}