问题
I faced with problem that React didnt wait evalating values. I have about 10 GET requests in useEffect and then placing it on hook state:
const [data,setData]=useState()
useEffect(async()=>{
//here axios requests
setData('here retrieved data above');
},[]);
I wrapped in async function but it not helping and my react code starting without data from axios requests, but at console i see data from every request with mark "value below was evaluated just now". How I can wait for evaluating? As I understand it related with mutating objects - https://www.freecodecamp.org/news/mutating-objects-what-will-be-logged-in-the-console-ffb24e241e07/ But didnt understand how to solve it
My code:
const SmallGrid = (props)=>{
return <div>
<h1>{props.name}</h1>
{props.elements && props.elements.map((el, idx)=>{
return <Link to={`${el.url.split("http://swapi.dev/api")[1].slice(0, -1)}`} className={styles.links}>{el.name}</Link>
})}
</div>
};
function UniPage({match}) {
const[data, setData] = useState({});
const getData = async () => {
try {
const firstData = await axios.get(`https://swapi.dev/api${match.url}`);
console.log(firstData.data);
let addData = {};
await Promise.all(
Object.keys(firstData.data).map((key)=>{
if(Array.isArray(firstData.data[key])){
let tempArray = [];
firstData.data[key].map((url)=>{
axios.get(url)
.then((data)=>{
tempArray.push(data.data)
})
});
addData[key] = tempArray;
}
})
).then(result=>{
console.log(addData);
setData(Object.assign(firstData.data,addData));
})
} catch (err ) {
// errors
console.log(err,"connection error")
}
}
useEffect(() => {
getData()
}, []);
With this code I missing part of data from nested requests and getting it in console like evaluated value.
回答1:
Unfortunately, useEffect cannot be made to wait for promises to resolve. This is because, in React, the effect hook expects the value returned by the function that is passed to it to be a cleanup function. Therefore, handing an async function to it will result in the returned Promise being interpreted as such.
A typical workaround is to use Promise.prototype.then() (outlined below as Strategy A).
Another solution is to shift all async logic into separate functions that can be made to wait (outlined below as Strategy B). This tends to be the preferred as it allows for the opportunity to insinuate what is happening via the name of the function and leads to neater code.
See below for a practical example.
// State.
const [data, setData] = useState()
// Did Mount.
useEffect(() => {
// Strategy A.
axios.get('/endpoint').then(response => setData(response.data))
// Strategy B.
const fetchData = async () => {
const {data} = await axios.get('/endpoint')
setData(data)
}
fetchData()
}, [])
来源:https://stackoverflow.com/questions/63125026/how-to-wait-for-evaluating-values-in-react-from-nested-requests