编辑(突变)对象属性在NGRX中的还原器中

发布于 2025-02-13 20:25:57 字数 1021 浏览 0 评论 0原文

尝试编辑对象内的属性时,我会遇到麻烦。我正在使用Pokeapi获取Pokémon,然后用按钮将其添加到购物车中。

接口

export interface PokemonModel {
  name: string;
  url: string;
  quantity: number;
  isAdded: boolean;
}

action

export const addToCart = createAction(
  '[Cart List] Add To cart',
  props<{ pokemon: PokemonModel }>()
);

还原器

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],
    ],
  };
}),

函数

addPokemon(pokemon: any) {
  this.store.dispatch(addToCart({ pokemon }));
}

是,我需要编辑ISADDED 属性。

我已经尝试使用object.preventextensions(Pokemon)无论我是在属性上方还是下方添加,结果都是相同的。

I'm having troubles when trying to edit a property inside an object. I'm using PokeApi to fetch Pokémon 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 edit the 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你是暖光i 2025-02-20 20:25:57

小提醒:由于还原器是纯函数您不能突变 state您需要创建副本并编辑副本(此 所有函数编程princicples

let pokemonCopy = {...pokemon, isAdded: true}

。 >同样 不起作用。

时间,我

 return {
    ...state,
    loading: false,
    error: false,
    pokemons: [
      ...state.pokemons.filter((pk) => pk.name !== pokemon.name),
      pokemonCopy,
    ],
  };

认为这对您

return {
    ...state,
    loading: false,
    error: false,
    pokemons: [
      ...state.pokemons.map((pk) => pk.name == pokemon.name ? pokemonCopy : pk),
    ],
  };

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),
    ],
  };

你怎么这么可爱啊 2025-02-20 20:25:57

不建议更改还原器内部的有效载荷,因为它们是纯粹的功能。我建议您在派遣前更新有效载荷,如下所示。派遣后,您不必担心编辑有效载荷

addPokemon(pokemon: any) {
  pokemon.isAdded = true;
  this.store.dispatch(addToCart({ pokemon }));
}

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 }));
}
煮茶煮酒煮时光 2025-02-20 20:25:57

如果您尽可能更好地干净,例如,

on(storeActions.updateCurrentChat, (state, { currentChat }) => {
    return {
      ...state,
      currentChat: { ...currentChat },
    };
  })

您可以实际上可以突变数据并传递它们,

public stopPriting(id: string) {
    const updatedCurrenctChat = structuredClone(this.currentChat$);
    const message = updatedCurrenctChat.messages.find(
      (chat) => chat.id === id
    ) as ConvI;
    // WhichType<typeof this.currentChat$,'isPrinted'>

    (message as MeowGPTI).isPrinted = true;
    // (<MeowGPTI>message).isPrinted = true;

    this.store.dispatch(
      storeActions.updateCurrentChat({ currentChat: updatedCurrenctChat })
    );
  }

这是一种更好的方法,我相信有不同的方法来克隆对象,例如json.parse(json.stringify(obj obj(obj) )loadash,但这全部取决于您的情况

It is a much better approach if you better your reducer's as clean as possible like this for example

on(storeActions.updateCurrentChat, (state, { currentChat }) => {
    return {
      ...state,
      currentChat: { ...currentChat },
    };
  })

where you could actually mutate the data and pass them

public stopPriting(id: string) {
    const updatedCurrenctChat = structuredClone(this.currentChat$);
    const message = updatedCurrenctChat.messages.find(
      (chat) => chat.id === id
    ) as ConvI;
    // WhichType<typeof this.currentChat$,'isPrinted'>

    (message as MeowGPTI).isPrinted = true;
    // (<MeowGPTI>message).isPrinted = true;

    this.store.dispatch(
      storeActions.updateCurrentChat({ currentChat: updatedCurrenctChat })
    );
  }

I believe there's different ways of cloning objects like JSON.parse(JSON.stringify(obj) or with loadash but it all depends on your case

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文