I'm still struggling with React Natives rendering order. I'm fetching the API, then I filter this data and finally I'm manipulating the data. When I first load the app, it does not show the Data appropriately only when I'm saving within my code editor it shows up.
My simplified code:
const [data, setData] = useState([]);
const [sumPost, setSumPost] = useState(0);
const [sumProd, setSumProd] = useState(0);
useEffect(() => {
const unsubscribe = db.collection("Dates").where("projektName", "==", Projektname).onSnapshot(snapshot => (
setData(
snapshot.docs.map((doc) => ({
id: doc.id,
data: doc.data(),
})))
))
return unsubscribe;
}, [])
const produktionsFilter = data.filter( x =>
x.data.jobtype == "Produktion"
);
const postFilter = data.filter( x =>
x.data.jobtype == "Postproduktion"
);
const terminFilter = data.filter( x =>
x.data.jobtype == "Termin"
);
let i;
const addPostProdTage = () => {
const post = [];
const prod = [];
for(i=0; i < postFilter.length; i++){
const p = postFilter[i].data.alleTage.length;
post.push(p)
}
for(i=0; i < produktionsFilter.length; i++){
const l = produktionsFilter[i].data.alleTage.length;
prod.push(l)
}
setSumPost(post.reduce(function(a, b){
return a + b;
}, 0));
setSumProd(prod.reduce(function(a, b){
return a + b;
}, 0));
}
useEffect(() => {
addPostProdTage();
}, [])
return(
<View>
<Text>{sumPost}</Text>
<Text>{sumProd}</Text>
</View>
)
sumProd should be 18 and sumPost should be 3. Right now it is showing 0 on both, because both states are empty arrays initially. It needs to some sort refresh.
I'm sure, there are more efficient ways to code this, but I need help to understand, why my data is not showing appropriately when I first load the app, because I'm running into this problem over and over again.
Thanks to all the advise I got on here, so for future reference this is how I solved this:
I filtered the data inside snapshot:
useEffect(() => {
const post = db
.collection("Dates")
.where("projektName", "==", Projektname)
.where("jobtype", "==", "Postproduktion")
.onSnapshot((snapshot) =>
setPost(
snapshot.docs.map((doc) => ({
id: doc.id,
data: doc.data(),
}))
)
);
return post;
}, []);
I had unnecessary steps to do my calculation. I could simplify this into a single function:
const revData = () => {
setSumPost(
post.reduce(function (prev, cur) {
return prev + cur.data.alleTage.length;
}, 0)
);
};
And finally, I had a useEffect to call that function after the data has been fetched using the dependency array:
useEffect(() => {
revData();
}, [post]);
You are creating local variables that go out of scope. You would be able to catch this error if you were using typescript instead of javascript.
You want to instead create state objects like this:
const [sumPost, setSumPost] = useState(0)
const [sumProd, setSumProd] = useState(0);
And then set the values of those objects as shown:
setSumPost(postproduktionsTage.reduce(function(a, b){
return a + b;
}, 0));
setSumProd(produktionsTage.reduce(function(a, b){
return a + b;
}, 0));
And then you can use it as you desire:
return(
<View>
<Text>{sumPost}</Text>
<Text>{sumProd}</Text>
</View>
)