I have a list component that rendered by the Map, this is how I define the data in react function component:
const [projMap, setProjMap] = useState<Map<number, FolderModel>>(new Map<number, FolderModel>());
When I set the map in react function component like this:
React.useEffect(() => {
if (folderProjList && folderProjList.length > 0) {
if (currFolder) {
let cachedExpand = projMap.get(currFolder.id)?.expand;
let folderModel: FolderModel = {
expand: cachedExpand ? cachedExpand : true,
projects: folderProjList
};
projMap.set(currFolder.id, folderModel);
setProjMap(projMap);
}
}
}, [folderProjList]);
did not trigger the rerender where using the projMap to render UI. Then I change the style like this:
React.useEffect(() => {
if (folderProjList && folderProjList.length > 0) {
if (currFolder) {
setProjMap((prevMapState) => {
const newMapState = new Map<number, FolderModel>(prevMapState);
let cachedExpand = newMapState.get(currFolder.id)?.expand;
let folderModel: FolderModel = {
expand: cachedExpand ? cachedExpand : true,
projects: folderProjList
};
newMapState.set(currFolder.id, folderModel);
return newMapState;
});
}
}
}, [folderProjList]);
the rerender works fine. the UI was always keep to newest. what is the different with the two type of setState? why the second style works with immediate rerender but the fisrt style did not?
>Solution :
In the first one you’re mutating the map (by adding an entry) and then setting the mutated map as state.
In the second example, you’re creating a new map and setting the new map as state, no mutation.