If you use a function as an argument for useState
it has to be synchronous.
The code your example shows is asynchronous - it uses a promise that sets the value only after the request is completed
You are trying to load data when a component is rendered for the first time - this is a very common use case and there are many libraries that handle it, like these popular choices: https://www.npmjs.com/package/react-async-hook and https://www.npmjs.com/package/@react-hook/async. They would not only set the data to display, but provide you a flag to use and show a loader or display an error if such has happened
This is basically how you would set initial state when you have to set it asynchronously
const [allads, setAllads] = useState([]);
const [loading, setLoading] = useState(false);
React.useEffect(() => {
// Show a loading animation/message while loading
setLoading(true);
// Invoke async request
Axios.get(`/admin/getallads`).then((res) => {
const ads = res.data.map((item) => item._id);
// Set some items after a successful response
setAllAds(ads):
})
.catch(e => alert(`Getting data failed: ${e.message}`))
.finally(() => setLoading(false))
// No variable dependencies means this would run only once after the first render
}, []);
Think of the initial value of useState
as something raw that you can set immediately. You know you would be display handling a list (array) of items, then the initial value should be an empty array. useState
only accept a function to cover a bit more expensive cases that would otherwise get evaluated on each render pass. Like reading from local/session storage
const [allads, setAllads] = useState(() => {
const asText = localStorage.getItem('myStoredList');
const ads = asText ? JSON.parse(asText) : [];
return ads;
});