Доступ к вложенному объекту внутри массива в Angular NGXS

Я успешно реализовал функцию удаления комментариев в своем приложении Angular. Моя проблема теперь связана с функцией лайка комментария. Как мне реализовать подобную функцию. У меня есть переменная is_liked, чтобы определить, нравится она мне или нет. Значение = 0 означает, что ему не нравится, а значение = 1 нравится. Пожалуйста, посмотрите мою ссылку на stackblitz здесь

НАЖМИТЕ НА ЭТУ ССЫЛКУ

onLikeComment(data: Comment) {
    this.store.dispatch(new LikeComment(data)).subscribe();
  }

@Action(LikeComment)
  likeComment(
    ctx: StateContext<PostStateModel>,
    { payload }: LikeComment
  ) {
    if (payload.is_liked === 1) {
      payload.is_liked = 0;
    } else {
      payload.is_liked = 1;
    }
    const state = ctx.getState();
    ctx.setState(
      patch({
        post: {
          ...state.post,
          comments: [
            ...state.post.comments,
            updateItem<any>(name => name === payload.id, payload)
          ]
        }
      })
    );
  }

person Joseph    schedule 24.11.2019    source источник
comment
Обновления состояния должны быть неизменяемым, а не прямое обновление данных, как и в случае со свойством is_liked   -  person Yurii    schedule 24.11.2019
comment
@Юрий. Можете ли вы помочь мне? Можете ли вы отредактировать мой стек? Спасибо   -  person Joseph    schedule 24.11.2019


Ответы (2)


Основная проблема в вашем коде - это использование оператора состояния updateItem. Этот оператор должен быть назначен полю в объекте, который вы передаете оператору patch.

patch({
  field1: 'someValue',
  comments: updateItem<Comment>(
    comment => comment.id === 0,
    {id: 0, text: 'This is a nice post!', is_liked: 1}
  )
})

справочник по updateItem

Вторая проблема, которую я вижу с вашим обработчиком действий, заключается в том, что вы неправильно используете оператор patch. Этот оператор позволяет присваивать значения только тем полям, которые вы хотите изменить, например StateContext.patchState.

Я бы изменил ваш код на этот:

  @Action(LikeComment)
  likeComment(
    ctx: StateContext<PostStateModel>,
    { payload }: LikeComment
  ) {
    const isLiked = payload.is_liked === 1 ? 0 : 1;

    ctx.setState(
      patch({
        // Apply patch on the post to only update the comments field
        post: patch({
          // Apply updateItem to make the operator only update the item that matches the condition
          comments: updateItem<Comment>(
            comment => comment.id === payload.id,
            // Apply a patch on the found comment to only change the is_liked field.
            patch({is_liked: isLiked}))
        })
      })
    );
  }

Надеюсь, это имеет смысл. Это мой первый ответ на SO :)

Вот обновленный stackblitz

person poloagustin    schedule 24.11.2019
comment
По какой причине вы используете .setState(patch()) вместо .patchState()? - person Erik Philips; 25.08.2020

вы можете обработать функцию «подобное» следующим образом.

ctx.setState(
      patch({
        post: {
          ...state.post,
          comments: this.getUpdatedComments(state, payload)
        }
      })
    );

getUpdatedComments(state, payload): any {
      let comments = [];
      state.post.comments.forEach((cmt) => {
          if (cmt.id === payload.id) {
              cmt = Object.assign({}, cmt);
              cmt.is_liked = payload.is_liked === 1 ? 0 : 1;
          }
          comments.push(cmt);
      });
      return comments;
  }

Вот обновленная демонстрация - https://stackblitz.com/edit/ngxs-delete-like-dek3s1.

person Allabakash    schedule 24.11.2019
comment
Спасибо за это, но за то, что вы изменили состояние. Можете ли вы изменить его, не изменяя состояние и используя операторов состояний от NGXS? Спасибо - person Joseph; 24.11.2019