Reputation: 35
I'm trying to get data from my API then modifying it, I tried this:
const [reports, setReports] = useState([]);
const [workers, setWorkers] = useState([]);
const [newReports, setNewReports] = useState([]);
useEffect(() => {
(async () => {
await get_user_data().then((dataRes) => {
axios
.get('/api/reports/?my_business=' + dataRes.id)
.then((dataRes) => {
setReports(dataRes.data);
return dataRes.data[0].my_business;
})
.then((dataRes) => {
axios
.get('/api/workers/?my_business=' + dataRes)
.then((dataRes) => {
setWorkers(dataRes.data);
})
.then(() => {
setNewReports(fix_data());
});
});
});
})();
}, []);
I got the reports and the workers, but when I set newReports I only get them in the first render, if I refresh I lose the data in new reports, that's because setNewReports(fix_data()) don't wait for the reports and the workers to be fetched.
Here's my fix_data()
function:
function fix_data() {
let w = {};
let r = {};
let rep = [];
reports.forEach((report) => (w[report.worker_id] = workers.find((worker) => worker.id === report.worker_id)));
reports.forEach(
(report) => (
(r = report), (r.worker_id = w[report.worker_id].first_name + ' ' + w[report.worker_id].last_name), rep.push(r)
),
);
return rep;
}
What's wrong with my useEffect function? I do call setNewReports(fix_data()) inside then so why it doesn't wait for the data to be fetched? Thank you
Upvotes: 1
Views: 417
Reputation: 35
Here's the code that worked after small fixes on @black lotus's answer:
const [reports, setReports] = useState([]);
const [workers, setWorkers] = useState([]);
const [newReports, setNewReports] = useState([]);
const [dataRes, setDataRes]= useState([]);
const get_reports = async (dataRes) =>{
const Report_Res = await axios.get('/api/reports/?my_business=' + dataRes)
setReports(Report_Res.data);
}
const get_worker_data = async (dataRes)=>{
const Worker_Res = await axios.get('/api/workers/?my_business=' + dataRes)
setWorkers(Worker_Res.data);
}
const get_user = async (dataRes)=>{
const user_Res = await get_user_data()
setDataRes(user_Res);
}
useEffect(()=>{
get_user()
},[])
useEffect(()=>{
get_worker_data(dataRes)
get_reports(dataRes)
},[dataRes])
useEffect(()=>{
setNewReports(fix_data())
},[reports, workers])
Upvotes: 1
Reputation: 130
const [reports, setReports] = useState([]);
const [workers, setWorkers] = useState([]);
const [newReports, setNewReports] = useState([])
const get_reports = async (dataRes) =>{
const Report_Res = await axios.get('/api/reports/?my_business=' + dataRes.id)
setReports(Res.data);
}
const get_worker_data = async (dataRes)=>{
const Worker_Res = await axios.get('/api/workers/?my_business=' + dataRes)
setWorkers(dataRes.data);
}
useEffect(()=>{
get_user_data()
},[])
useEffect(()=>{
get_reports(dataRes)
get_worker_data(dataRes)
},[dataRes])
useEffect(()=>{
setNewReports(fix_data())
},[reports, workers])
@alaa yahia It's better if you practice clean code. :)
1.Try to wrap up your each api call in separate function. It looks cleaner and easy to understand.
Call the functions in useEffect. Look at the 1st useEffect. they will populate the states of user Data. 2nd useEffect fetches the worker and report data which depends on DataRes. So add DataRes in dependency array of 2nd useEffect.
call the setNewReports(fix_data()) in 3nd useEffect. and it will make sure It fixes the data when reports and workers data are present. Look at the dependency array- [reports, workers] at the end of 3rd useeffect. That means This useEffect will run, when these [reports, workers] changes.
N.B- I wrote those codes without running. Forgive if any Typing mistake presents.
Upvotes: 2