I'm having troubles when trying to add a new property inside an object. I'm using PokeApi to fetch pokemons and then, with a button, add them into a cart.
Interface
export interface PokemonModel {
name: string;
url: string;
quantity: number;
isAdded: boolean;
}
Action
export const addToCart = createAction(
'[Cart List] Add To cart',
props<{ pokemon: PokemonModel }>()
);
Reducer
on(addToCart, (state, { pokemon }) => {
pokemon.isAdded = true; // <-- Cannot add property isAdded, object is not extensible
return {
...state,
loading: false,
error: false,
pokemons: [
...state.pokemons.filter((pk) => pk.name !== pokemon.name),
...[pokemon],
],
};
}),
Function
addPokemon(pokemon: any) {
this.store.dispatch(addToCart({ pokemon }));
}
The thing is I need to add a new value for isAdded
property. I have tried with Object.preventExtensions(pokemon)
no matter if I add above or below the property, the result is the same.
CodePudding user response:
Small reminder: Because reducers are pure functions
you can't mutate
the state
manually, you need to create a copy and edit the copy (this is all functional programming princicples
.
Create a copy of Pokémon:
let pokemonCopy = {...pokemon, isAdded: true}
And for the spread operator, you're combining both computed property
in objects and spread operator
at the same time, which I don't think it's gonna work for you.
You need to simply append it to the new state
return {
...state,
loading: false,
error: false,
pokemons: [
...state.pokemons.filter((pk) => pk.name !== pokemon.name),
pokemonCopy,
],
};
and if the order matter to you, I'd recommend
return {
...state,
loading: false,
error: false,
pokemons: [
...state.pokemons.map((pk) => pk.name == pokemon.name ? pokemonCopy : pk),
],
};
CodePudding user response:
It is not recommended to change the payload inside reducers as they are intended to be pure functions. I would recommend you to update the payload before dispatching as shown below. Once dispatched, you should not be worrying about editing payload
addPokemon(pokemon: any) {
pokemon.isAdded = true;
this.store.dispatch(addToCart({ pokemon }));
}
CodePudding user response:
You can add directly to the state.
on(addToCart, (state, { pokemon }) => {
return {
...state,
loading: false,
error: false,
pokemons: [
...state.pokemons.filter((pk) => pk.name !== pokemon.name),
...[{
...pokemon,
isAdded:true
}],
],
};
}),