I want my axios query 1 is finish to execute my 2nd - reactjs

I would like my "userid" to no longer be null for executing my 2nd request. the code is
const [userid, setUserid] = useState(null)
const userConnected = useEffect(() => {
(async () => {
try {
const resp = await httpClient.get("//localhost:5000/#me");
setUserid(resp.data.id)
console.log(resp.data.id)
} catch (error) {
console.log("Not authenticated");
}
})();
}, []);
const fetchUserItem = async () => {
try {
const owner = await axios({
url: `${baseUrl}/additem/owner/${userid}`, //problem:
//user.id = Null
//so its like ${baseUrl}/additem/owner/null
method: 'get'
})
const { events } = owner.data
console.log(owner.data)
setitemList(events)
}
catch {
console.log('error')
}
}
i think the problem is:
as the 2 requests are carried out at the same time the {userid} = null (usestate)
so I have http://5000/additem/owner/null
i must have http://5000/additem/owner/12423

Try it, maybe this would work out:
const [userid, setUserid] = useState(null);
const userConnected = useEffect(() => {
// to run below function only when userid is null
userid == null
? (async () => {
try {
const resp = await httpClient.get("//localhost:5000/#me");
setUserid(resp.data.id);
console.log(resp.data.id);
} catch (error) {
console.log("Not authenticated");
}
})()
// call fetchUserItem inside useEffect
: (async () => {
await fetchUserItem();
})();
}, [userid] /* define userid in dependency array */);

Related

useEffect didnt run

So i have this function that i want to run once when the app start. This function task is to create userId then i will run another function to fetch data from firebase with the userId that created before. But the fetch function didn't start or it didnt do the task well, there is no sign of error, that's what make it more confusing. If i press the fetch function by button it work correctly.
the state
const [task, setTask] = useState(); // bisa di sebut sebagai controller text input
const [taskItems, setTaskItems] = useState([]); // state untuk list task
const [userId, setUserId] = useState();
const [isLoading, setIsLoading] = useState(true);
const baseUrl =
'https://react-http-post-RANDOM_KEY-default-rtdb.firebaseio.com/task/' + userId;
this is function to create userId function on init app
const handleCreateUser = async () => {
setIsLoading(true);
try {
const value = await AsyncStorage.getItem('userId');
if (value !== null) {
setUserId(value);
} else {
const uniqueId = makeid(6);
await AsyncStorage.setItem('userId', 'user' + uniqueId);
setUserId('user' + uniqueId);
}
await fetchDatabase();
} catch (error) {
console.log('errorrr AsyncStorage' + error);
}
setIsLoading(false);
};
this is function to fetch data from firebase
const fetchDatabase = async () => {
console.log('infinite looping');
try {
const response = await fetch(baseUrl + '.json');
if (!response.ok) {
throw new Error('Something went wrong!');
}
const data = await response.json();
// looping Map/Object dengan key sebagai indexnya
const loadedTask = [];
for (var id in data) {
loadedTask.push({
key: id,
text: data[id].text,
isComplete: data[id].isComplete,
});
}
setTaskItems(loadedTask);
} catch (error) {
setError(error.message);
}
};
this is how i call the useEffect
useEffect(() => {
handleCreateUser();
}, []);
The first thing I see is that you are not using await correctly. It should be before fetchDatabase(); function that is inside handleCreateUser like so:
await fetchDatabase();
The word await is there when you have to call an asynchronous function and you have to wait for this function to be completed.
Edit
To use only one useEffect you can check if your fetch function received your data by:
// or whatever statusCode you get when the data are present
if(reponse.statusCode === 200) {
// the await is not needed because it is present for the reponse abov
const data = response.json();
// looping Map/Object dengan key sebagai indexnya
const loadedTask = [];
for (var id in data) {
loadedTask.push({
key: id,
text: data[id].text,
isComplete: data[id].isComplete,
});
}
setTaskItems(loadedTask);
}
i got the answer, by using 2 useEffect
useEffect(() => {
handleCreateUser();
}, []);
useEffect(() => {
fetchDatabase();
}, [userId]);

React useEffect gives react-hooks/exhaustive-deps error on publishing

My .net core react web application works fine, except that when I try to publish it gives me the following error:
Occurred while linting C:\.....Fetch.js: 79
Rule: "react-hooks/exhaustive-deps"
This is my code:
const populateTable1Data = async () => {
var response = await axios.get(apiurl + { params: { id: props.id1 } });
var data = await response.data;
setTable1Data(data);
}
const populateTable2Data = async () => {
var response = await axios.get(apiurl + { params: { id: props.id2 } });
var data = await response.data;
setTable2Data(data);
setLoading(false);
}
useEffect(() => {
const load = async () => {
await populateTable1Data();
await populateTable2Data();
setLoading(false)
}
load()
}, []);
Problem is that I have a very similar useEffect inside another component which doesn't give errors though:
const populateTableData = async () => {
const response = await axios.get(apiurl + key);
const data = await response.data;
setTableData(data);
setLoading(false);
}
useEffect(() => {
populateTableData();
}, [])
If anyone has the same problem, I solved by doing this:
const populateTable1Data = async (dataProps) => {
var response = await axios.get(apiurl + { params: { id: dataProps.id1 } });
var data = await response.data;
setTable1Data(data);
}
const populateTable2Data = async (dataProps) => {
var response = await axios.get(apiurl + { params: { id: dataProps.id2 } });
var data = await response.data;
setTable2Data(data);
setLoading(false);
}
useEffect(() => {
const load = async () => {
await populateTable1Data(props);
await populateTable2Data(props);
setLoading(false)
}
load()
}, [props]);
I essentially passed the props on the function call, I don't know why does it have to be this way, I'll leave the answer here in case anyone else needs it while waiting for someone to be kind enought to explain the reason for this.

Can't fetch data with Axios and React, getting an Promise and Undefined

I'm trying to fetch some data with Axios and React, But I'm having a problem resolving the promise and setting it on the state, that's weird.
Here is the Base:
export const fetchUserById = (username) => client.get(`/${username}`);
Here is the Call:
export const getUserById = async (username) => {
try {
const response = await api.fetchUserById(username);
const data = await response.data;
return data;
} catch (error) {
return error;
}
};
Here is in React:
const [user, setUser] = useState();
useEffect(() => {
const data = getUserById(params.username); // this gets the username and its working
setUser(data)
}, [])
useEffect(() => {
console.log("this is user: ", user)
}, [user])
If I console log user, I get undefined, If I console log data i get a promise.
getUserById is declared async so it implicitly returns a Promise that callers should either await or use a Promise chain on.
useEffect(() => {
const data = getUserById(params.username);
setUser(data); // <-- logs only the returned Promise object!
}, [])
async/await
useEffect(() => {
const getUser = async () => {
try {
const data = await getUserById(params.username);
setUser(data);
} catch(error) {
// handle error, log, etc...
}
};
getUser();
}, []);
Promise chain
useEffect(() => {
getUserById(params.username)
.then(data => {
setUser(data);
})
.catch(error => {
// handle error, log, etc...
});
};
}, []);
Or you could as well do:
useEffect(() => {
// fetch data
(async () => {
try {
const data = await getUserById(params.username);
// set state
setUser(data)
} catch(error) {
// handle error, log, etc...
// set init state
setUser(null)
}
})();
}, []);

Why am i getting an undefined output when I try to access value returned from async method

I have the following method which returns an object with 3 fields inside a different file named localStorage:
const getUserProfileData = async () => {
try {
await AsyncStorage.getItem(CONSTANTS.USER_PROFILE).then((item) => {
let retrievedProfile = JSON.parse(item);
return retrievedProfile;
});
} catch (e) {
throw e;
}
};
here is my file profile.js:
useEffect(() => {
const retrieveProfileData = async () => {
let retProfile = await localStorage.getUserProfileData();
console.log("check what: ",retProfile);
};
retrieveProfileData();
}, []);
inside the use effect, when I attempt to log out the result I get an output of:
check what: undefined
I have read other forums on similar problems to this but I can't seem to notice where I'm going wrong?
I think it has to do with you mixing async and .then(). Try this way:
const getUserProfileData = async () => {
try {
const result = await AsyncStorage.getItem(CONSTANTS.USER_PROFILE)
const retrievedProfile = JSON.parse(result);
return retrievedProfile;
} catch (e) {
throw e;
}
};
const getUserProfileData = async () => {
return AsyncStorage.getItem(CONSTANTS.USER_PROFILE);
};
useEffect(() => {
const retrieveProfileData = async () => {
try {
let retProfile = JSON.parse(await localStorage.getUserProfileData());
console.log("check what: ",retProfile);
} catch (error) {
// handle error
}
};
retrieveProfileData();
}, []);

http fetch returns true instead of actual data

I am trying to use a http hook in another component to send a get request. The post request is working fine. But when I try a get request I just get back 'true' when I console log my result. When I send the same get request in postman I get the correct data back, so it isn't a backend problem.
The hook:
import { useState, useCallback, useRef, useEffect } from "react";
export const useHttpClient = () => {
const [isLoading, setIsLoading] = useState(false);
const [errors, setErrors] = useState();
const [success, setSuccess] = useState(false);
const activeHttpRequests = useRef([]);
const sendRequest = useCallback(
async (url, method = "GET", body = null, headers = {}) => {
setIsLoading(true);
const httpAbortController = new AbortController();
activeHttpRequests.current.push(httpAbortController);
try {
setErrors();
setSuccess(false);
const response = await fetch(url, {
method: method,
body: body,
headers: headers,
signal: httpAbortController.signal,
});
const responseData = await response.json();
activeHttpRequests.current = activeHttpRequests.current.filter(
(reqCtrl) => reqCtrl !== httpAbortController
);
if (response.status !== 200) {
setErrors(responseData);
return responseData;
} else {
setSuccess(true);
return true;
}
} catch (err) {
//setErrors(err.message);
setErrors([
"There was an error submitting your form, please try again later.",
]);
setIsLoading(false);
throw err;
}
},
[]
);
//useEffect can also be used for cleanup
useEffect(() => {
return () => {
activeHttpRequests.current.forEach((AbortController) =>
AbortController.abort()
);
};
}, []);
return { isLoading, errors, sendRequest, success };
};
The server call:
useEffect(() => {
const fetchFaq = async () => {
try {
const responseData = await sendRequest(
"http://localhost:8000/api/myEndpoint"
);
console.log(responseData);
setLoadedFaq(responseData);
} catch (err) {}
};
fetchFaq();
}, [sendRequest]);
Your hook returns true if it gets a 200 response code:
if (response.status !== 200) {
setErrors(responseData);
return responseData;
} else {
setSuccess(true);
return true;
}
It only returns responseData if it gets a non-200 code. Just return the data from the hook..

Resources