I am fetching data from api, then mapping it. When I try to print values inside it it prints correctly. But when I try to print same after sometime in other function it shows empty. This is the only 2 places where I have used my map nowhere else.
const catmap = new Map();
useEffect(() => {
// fetch categories
getCategories().then((res) => {
setCategories(res.data);
res.data.map(
(c) => {
catmap.set(c._id, c.name);
}
);
console.log("mycate len", catmap); //correctly map the values
console.log("mycate len", catmap.size); //and shows it size
});
}, []);
useEffect(() => {
let currentUrlParams = new URLSearchParams(window.location.search);
console.log("mycate len", catmap);
console.log("mycate len", catmap.size); //Here It shows empty and zero size
}, [categoryIds]);
CodePudding user response:
it's important to understand how state is handled in React. Any value that is subject to change, and for which changes need to be tracked, within the lifecycle of the components, should be wrapped in state.
So in React, you can use useState
.
const catmap = new Map();
should become
const [catmap, setCatmap]= useState(new Map());
Now you have a value catmap
that you can use throughout your component. And a setter setCatmap
that you can use to update the value.
Your current effect is mapping over the response data and using it to mutate the map, this works within the scope which is why logging in the effect seems to have updated the map, but React won't be able to track any updates.
But now you have a setter you can use that.
So can do
const nextMap = res.data.map((c) => {
catmap.set(c._id, c.name);
});
setCatmap(nextMap)
but references should also be updated for the changes to be tracked by React so you should also create a new map
setCatmap(new Map(nextMap))
Or if you want to update from current state, for example if there were already items in the map
setCatmap(
(current) =>
new Map([...current.entries(), ...res.data.map((c) => [c._id, c.name])]),
);