My ponent relies on local state (useState
), but the initial value should e from an http response.
Can I pass an async function to set the initial state? How can I set the initial state from the response?
This is my code
const fcads = () => {
let good;
Axios.get(`/admin/getallads`).then((res) => {
good = res.data.map((item) => item._id);
});
return good;
};
const [allads, setAllads] = useState(() => fcads());
But when I try console.log(allads)
I got result undefined
.
My ponent relies on local state (useState
), but the initial value should e from an http response.
Can I pass an async function to set the initial state? How can I set the initial state from the response?
This is my code
const fcads = () => {
let good;
Axios.get(`/admin/getallads`).then((res) => {
good = res.data.map((item) => item._id);
});
return good;
};
const [allads, setAllads] = useState(() => fcads());
But when I try console.log(allads)
I got result undefined
.
-
Where did you do
console.log(allads)
? – MacOS Commented Dec 21, 2020 at 9:36 - I make a button and do onclick to console.log(allads) @MacOS – test tet Commented Dec 21, 2020 at 9:42
- Use a useEffect hook and make the server call inside that. – adiga Commented Dec 21, 2020 at 9:42
-
Also, you can't use
good = res.data
inside the callback andreturn good
outside.return
is called before the callback is run. How do I return the response from an asynchronous call? – adiga Commented Dec 21, 2020 at 9:46 - I tried as you said but still got undefined @adiga – test tet Commented Dec 21, 2020 at 9:54
2 Answers
Reset to default 4If 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 pleted
You are trying to load data when a ponent is rendered for the first time - this is a very mon use case and there are many libraries that handle it, like these popular choices: https://www.npmjs./package/react-async-hook and https://www.npmjs./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;
});
You can use the custom hook to include a callback function for useState
with use-state-with-callback npm package.
npm install use-state-with-callback
For your case:
import React from "react";
import Axios from "axios";
import useStateWithCallback from "use-state-with-callback";
export default function App() {
const [allads, setAllads] = useStateWithCallback([], (allads) => {
let good;
Axios.get("https://fakestoreapi./products").then((res) => {
good = res.data.map((item) => item.id);
console.log(good);
setAllads(good);
});
});
return (
<div className="App">
<h1> {allads} </h1>
</div>
);
}
Demo & Code: https://codesandbox.io/s/distracted-torvalds-s5c8c?file=/src/App.js
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744215216a4563522.html
评论列表(0条)