я могу изменить значение селектора? - PullRequest
0 голосов
/ 28 мая 2020

У меня есть приложение, использующее NGRX.

У меня вопрос, я знаю, что магазин - это место, доступное только для чтения, где вы не можете напрямую изменять объект. Но когда я использую селектор

Например, если у меня есть следующий селектор ngrx

export const getSelectedMission = (state: State): Readonly<IMission> => state.selectedMission;
export const selectedMission: MemoizedSelector<object, Readonly<string>> = createSelector(
  selectMissionState,
  getSelectedMissionId
);

Если в моем приложении я делаю это

this.store$.pipe(select(MissionsStoreSelectors.selectedMission)).subscribe((mission) => mission.name = "123")

Это допустимая операция ? или этого следует избегать?

Если я хочу выбрать часть в магазине и иметь возможность редактировать это значение (чтобы снова отправить действие в магазине), каков будет лучший способ? Должен ли я сделать так, чтобы весь мой селектор возвращал копию объекта / массива?

EDIT:

Это нормально, но только если вы делаете копию объекта.

Что, если я сделаю это в компоненте:

this.selectedMission$ = this.store$.pipe(select(MissionsStoreSelectors.selectedMission))

Затем в шаблоне я передаю это значение дочернему элементу

<app-child [mission]="selectedMission$ | async"></app-child>

И в дочернем элементе я так в какой-то момент

mission.name = "123"

Это отредактирует прямую ссылку на значение в магазине, верно? но дочерний компонент не должен заботиться о создании копии объекта перед его изменением.

Ответы [ 2 ]

1 голос
/ 28 мая 2020

Можно вернуть другой результат. Но вы должны клонировать объект следующим образом:

this.store$.pipe(select(MissionsStoreSelectors.selectedRouteId)).subscribe((mission) => ({...mission, name: "123"}))

EDIT после EDIT

Вся идея магазина заключается в том, что если вы измените значение объекта из магазина, оно должно быть через магазин. Поэтому, если ваш компонент по какой-либо причине хочет произвести изменения непосредственно в объекте из магазина, тогда компонент должен клонировать объект.

0 голосов
/ 01 июня 2020

если вы хотите изменить значение из хранилища, вам нужно его распространить, но здесь нужно быть очень осторожным, потому что, если значение является глубоким объектом, вам также нужно позаботиться о его вложенных значениях.

this.selectedMission$ = this.store$.pipe(
  select(MissionsStoreSelectors.selectedMission),

  // now we do a deep clone and can pass it anywhere.
  map(value => JSON.stringify(JSON.encode(value))),
);

Правильный способ - использовать outputs и actions вот так.

<app-child [mission]="selectedMission$ | async" (update)="update($event)"></app-child>

app-child должен в какой-то момент испускать

this.update.emit({
  ...this.mission,
  name: '123',
});

, а в родительском компоненте вы можете отправить действие.

update(mission): void {
  this.store.dispatch(new UpdateMission(mission));
}

В этом случае вам не нужна карта с JSON magi c.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...