This question already has answers here:
The useState set method is not reflecting a change immediately
(15 answers)
Async function in react doesn't react to state change
(5 answers)
Closed 1 year ago.
i have a problem to get my state value.
i have declared my state homeworks
const [homeworks, setHomeworks] = useState([])
I call a function in my useEffect
useEffect(()=>{
fetchHomeworks()
},[])
This function call a service for get data from my API. And when data loading i set my states and i load other function with state but i don't get state in my function initMercure()
const fetchHomeworks = async () => {
try {
let data
if (classroom_id === "all") {
data = await homeworksAPI.findAll()
} else {
data = await classroomsAPI.getHomeworks(classroom_id)
}
await setHomeworks(data)
await initMercure()
} catch (error) {
console.log(error)
}
}
const initMercure = async () => {
console.log("homeworks (initMercure): ", homeworks) // <--- HERE, i have array blank []
}
I have try it but don't work
await setHomeworks(data, initMercure())
and
useEffect(()=>{
fetchHomeworks()
initMercure()
},[])
[RESOLVED]
useEffect(()=>{
fetchHomeworks()
fetchClassroom()
},[classroom_id])
useEffect(()=>{
if (homeworks.length>0) initMercure();
},[homeworks])
Thank you <3
Related
This question already has answers here:
React Hooks: how to wait for the data to be fetched before rendering
(4 answers)
Closed 1 year ago.
i have the following problem:
I'm fetching data (true or false value) from my database and want to save it to a useState.
I'm using async/await for the fetch. Because of that, the value saved to my state is undefined.
Here is my code:
const [myState, setMyState] = useState();
useEffect(() => {
myFunction()
async function myFunction () {
const req = await fetch("http://localhost:3001/api/getdata", {
headers: {
"x-access-token": sessionStorage.getItem("token")
}
})
const data = await req.json()
console.log("fetched data value: " + data)
// This is undefined in the console
setMyState(data)
// I already tried this, but await does not affect a setState
// const blah = await setMyState(data)
}
}, [])
How can i wait for the data to be fetched before saving it to the state?
Thanks for helping.
Since you have an async function, you can use then() promise handlers to only set the state once the data is fetched. Here's an example:
const [myState, setMyState] = useState();
useEffect(() => {
myFunction()
async function myFunction () {
// Call then() after using fetch to pass the result into a callback that saves state
fetch("http://localhost:3001/api/getdata", {
headers: {
"x-access-token": sessionStorage.getItem("token")
}
}).then(
(response) => response.json()
).then(
(data) => setMyState(data)
)
}
}, [])
Check out the official web api for fetch: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
What you have should work but you should set an initial value for your useState to an empty array or what ever it is your data will eventually be or at least null or undefined explicitly that way you know what state it is before its loaded
Below is stackblitz with a working example
https://stackblitz.com/edit/react-pimpje?file=src/App.js
function App() {
const [myState, setMyState] = React.useState(null);
React.useEffect(() => {
async function myFunction() {
/**
* https://apipheny.io/free-api/
*/
const req = await fetch('https://api.publicapis.org/entries');
const data = await req.json();
console.log('fetched data value: ', data);
setMyState(data);
}
myFunction();
}, []);
return <div>{myState && <pre>{JSON.stringify(myState, null, 2)}</pre>}</div>;
}
I want to fetch info from the API in useEffect, set it using setState and immediately use it for further filtering.
the code looks like this:
const[usersInfo, setUsersInfo] = setState('')
useEffect(()=>{
async function fetchUsers(){
const response = await fetch(`http://localhost:8083/api/patient/findAll`);
const json = await response.json();
setUsersInfo(json)
}
fetchUsers()
console.log('users info', usersInfo)
},[])
I tried to pass the dependency for usersInfo but then it is running in loop.
What can I do it to prevent this behavior?
You need to add a second useEffect that detects changes to usersInfo.
const [usersInfo, setUsersInfo] = setState("");
useEffect(() => {
async function fetchUsers() {
const response = await fetch(`http://localhost:8083/api/patient/findAll`);
const json = await response.json();
setUsersInfo(json);
}
fetchUsers();
// console.log("users info", usersInfo); // commenting out this code since it will always print empty string
}, []);
useEffect(() => {
if(usersInfo !== ""){
// Do stuff here with usersInfo
}
}, [usersInfo]);
This question already has answers here:
The useState set method is not reflecting a change immediately
(15 answers)
Closed 1 year ago.
I receive the data for the user object by an api call. Inside the getSelectedUser function, the console.log returns the filled user object. But in the console.log in the useEffect returns an empty object. What am I doing wrong?
Foo.tsx
const [user, setUser] = useState<IUser>(initialUser);
useEffect(() => {
getSelectedUser();
console.log(user);
}, []);
async function getSelectedUser() {
await getUserById(userId).then((data) => {
setUser(data);
console.log(data);
});
}
Service.tsx
export const getUserById = async (userId: string | number) => {
const user = ...;
const token = ...;
try {
const response = await fetch(`${apiurl}/${userId}`, {
method: 'GET',
...
}).then((res) => res.json());
return response;
} catch (error) {
console.log(error);
}
};
Because state only has new value when component re-render. So you can put console.log(user); out side the useEffect to check like this:
useEffect(() => {
getSelectedUser();
}, []);
console.log(user);
Or you can use other useEffect with dependencies to check the value of new state when compoent re-render
useEffect (() => {
console.log(user);
}, [user])
I'm trying to update state immediately after data comes in from the API. The data is coming in, I can see it using the console.log right below my API request. All of the data is right but for some reason, setState never sets in my hook. It just returns and empty array even after the console displays data.
const [experienceData, setExperienceData] = useState([]);
const { match = {} } = props;
useEffect(() => {
async function fetchData() {
if (Object.keys(match.params).length > 0) {
const response = await ApiService.getExperiences(match.params.experieneId);
console.log(response)
setExperienceData(response)
}
}
fetchData();
}, []);
I must be doing something wrong but I can't figure out what that is. Hoping someone on here has run into the same issue.
UPDATE: I just changed everything over the a class and duplicated the exact code on another file and ran into the exact same issue. The console updates with the data, but the setState on the line immediately after the data does not setState.
async componentDidMount() {
if (Object.keys(this.props.match.params).length > 0) {
const response = await ApiService.getExperiences(this.props.match.params.experieneId);
console.log(response[0])
this.setState({ experienceData: response[0], occurrenceData: response[0].occurrences });
}
}
You have to useSetState in a proper way, the issue is in the setExperienceData
const [experienceData, setExperienceData] = useState({response:""});
const { match = {} } = props;
useEffect(() => {
async function fetchData() {
if (Object.keys(props.match.params).length > 0) {
const response = await ApiService.getExperiences(match.params.experieneId);
console.log(response)
setExperienceData(experienceData => ({ ...experienceData, response: response }));
}
}
fetchData();
}, []);
return(<div>check {experienceData.response}</div>)
I see you left the dependency array empty. This tells React to run this effect only once: when the component first renders. If you want your useEffect to respect your state hook, put setExperienceData inside the dependency array
const [experienceData, setExperienceData] = useState([]);
const { match = {} } = props;
useEffect(() => {
fetchData();
}, [props.match.params]);
const async fetchData = () => {
if (Object.keys(match.params).length > 0) {
const response = await ApiService.getExperiences(match.params.experieneId);
console.log(response)
setExperienceData([...response])
}
}
Could you please try passing [match.params] as the second argument to your useEffect.
This question already has answers here:
The useState set method is not reflecting a change immediately
(15 answers)
Closed 10 months ago.
Code :
Result : Not have data in state
help me pls , thanks!
setState is asynchronous that's why you are seeing books as empty array. Here is a quote from the React docs:
The setState function is used to update the state. It accepts a new
state value and enqueues a re-render of the component.
One thing you may be doing wrong is in your useEffect callback. If your effect returns a function, React will run it when it is time to clean up. And you don't want the setState functions in fetchData to be invoked during clean up as the component will probably be unmounted.
If you just want the fetchData to only run once after the component mounts, here is a possible solution:
useEffect(() => {
// put the fetchData inside the effect
async function fetchData() {
setLoading(true);
const name = await getNameGroup();
const tmp = await getAll(name);
console.log(tmp);
setBooks(tmp);
console.log(books); // may not be the same as tmp, but you will see the updated state in the next render
setLoading(false);
}
fetchData();
},[]}
You should read more about useEffect hook in the React docs.
It's a stale closure problem.
Your useEffect where the fetchData is being called, has an empty dependency array. Within the fetchData function, which is inside useEffect, you are trying to print books which one first load, was initialized with an empty array.
All hooks hold the same reference to the variables with which they were initialized, till the dependencies change. To get an updated state, they depend on the dependency array. Since your dependency array doesn't specify books, it won't refresh the reference of books in your fetchData function either. Read more about the stale closure problem here
That's why your books variable is showing stale data.
export default function() {
// fetch data here
// runs only once because of empty dependency array
useEffect(() => {
let isCancelled = false
// define the fetchData inside the `useEffect` so that
// you can detect if the component has been unmounted
// using `isCancelled`
const fetchData = async () => {
const tmp = await getAll()
// only update state if component isn't unmounted
// if you try to update state on an unmounted component,
// React will throw an error
if (!isCancelled) {
setIsLoading(false)
setBooks(tmp)
}
}
if (!isCancelled) {
setIsLoading(true)
fetchData()
}
// cleanup
return () => {
isCancelled = true
}
}, [])
}
const [dataArray, setDataArray] = useState([]);
async function fetchData() {
try {
setIsLoading(true);
const response = await getNameGroup();
setDataArray(response);
} catch(error) {
// handle error
} finally {
setIsLoading(false);
}
}
This is an example code that is working and you can apply:
const [data, setData] = useState([]);
const [hasError, setErrors] = useState(false);
async function fetchData() {
const LibraryQuery = JSON.stringify({query: `query { species { id name description } }`});
const token = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
const res = await fetch('http://localhost:3000/graphql',{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': token
},
body: LibraryQuery
});
res
.json()
.then(res => setData(res.data))
.catch(err => setErrors(err));
}
useEffect(() => {
fetchData();
}, []);