I have a property in my state which is Map<string, object | 'error'> . When I get response from service I wish to update this map. I have tried below in the reducer
on(setMapData, (state, action) => {
const { data } = action
data.forEach( (value, id) => {
let dataMap = state.dataMap
dataMap.set(id, value)
return {
...state,
dataMap: {...state.dataMap, ...dataMap}
}
})
//Till here I can see dataMap having all the values in state.
return {
...state
//dataMap: state.dataMap
}
// But nothing is returned from here, my selectors are not getting invoked.
})
Below is my state object
export const initialState: dataState = {
loading: true,
dataMap: new Map<string, object | 'error'>()
}
Please help me in this issue. Thanks in advance.
CodePudding user response:
I can think of two solutions :
- Use
Immer
orImmutableJs
to generate a copy of Map at the reducer and then update the values. for example usingimmer
your code code be something like this:
on(setMapData, (state, { data }) => {
//Create a deep copy of the state dataMap and update it
let dataMap = produce(state.dataMap, newData => {
//loop through the received Map and get the new key,value pair
data.forEach((value, key) => {
//Set the new key, value pair of the map to the copied Map
newData.set(key, value)
});
});
//return the state with the new Map
return { ...state, dataMap };
});
- and I think this is the safest way: Your use case above is similar to what ngrx-entity offers. Try to not re-invent the wheel this package will help you update your map without worrying about the state (entities are Map) using their predefined methods.
CodePudding user response:
i can tell you, that using a Map-Object in an Action wont work. It will always show as empty. I dont exactly know why this is, but i believe the reason is, a Map is a Mutable-Object. Ngrx doesnt handle those at all. If you for exmaple use immutableJS on a Map, it would create a new Map().
Sorry for only half the answer.