I'm trying to SetState but inside it, I have to get some data that needs async/await and I know it can't be done so I wonder if is there any way I can do it properly
codesanbox: https://codesandbox.io/s/infallible-mendeleev-6641iw?file=/src/App.js:0-614
Edit: It's hard for me to get data before setState because If I only want to get data If the newValue satisfies a condition so Get data force to inside setState
import "./styles.css";
import { useEffect, useState } from "react";
export default function App() {
const [value, setValue] = useState([]);
const run = async () => {
setValue((oldValue) => {
const newValue = [...oldValue];
// do something makes newValue changes
if (newValue == true) { // if newValue satisfy a condition
const res = fetch(`https://fakestoreapi.com/products/${newValue.length}`);
const result = res.json();
newValue.push(result.title);
}
return newValue;
});
};
return (
<div className="App">
<button onClick={run}>get result</button>
{value.map((item, index) => {
return <h2 key={index}>{value[index]}</h2>;
})}
</div>
);
}
Why don't you run first the async code, and when the data are available set the state ?
const run = async (x) => {
const res = await fetch(`https://fakestoreapi.com/products/${x}`);
const result = await res.json();
setValue((oldValue) => {
// you have access to the fetched data here
const newValue = [...oldValue];
console.log(result.title);
return newValue;
});
};
And ofcourse the click handler should be
onClick={() => run(2)}
There's a React component called Suspense. I think it first appeared in v16, but in all honesty I have only used it with React v18, so unsure if it will work for you.
I'll refer you to a live demo I have: wj-config Live Demo
Here I use <Suspense> to wrap a component that requires data that is asynchronously obtained, just like when you use fetch().
Suspense works like this:
try..catch in said loading process.fallback property.fallback, React awaits the caught promise.I hear there are frameworks that provides the necessary mechanisms to use Suspense in a simple and expedite manner, but in my live demo I did it all myself. Is not too bad I think.
The procedure to use this is:
readXXX function that is a suspender function (a function that throws a promise).readXXX function has worked and returned the needed data.Here's the code I have in the live demo to create suspender functions:
function suspenderWrapper(promise) {
let isPending = true;
let outcome = null;
const suspender = promise.then(
(r) => {
outcome = r;
isPending = false;
},
(e) => {
outcome = e;
isPending = false;
}
);
return () => {
if (isPending) {
throw suspender;
}
return outcome;
};
}
Open up my live code's demo and look for App.js where all the magic is shown.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With