Читая документацию по ngrx, я понял, что для модификации хранилища используются только редукторы. Однако во время кодирования я заметил, что если я изменю любое поле в объекте, возвращаемом селектором, изменение будет применено к хранилищу. Я предполагаю, что получаю оригинальный объект из селектора.
В моем случае я заметил, что я изменяю хранилище, изменяя объект, возвращаемый селектором, при заполнении формы, где я связываю поля этого объекта.
Почему это возможно, почему селектор не возвращает только копию магазина? Каков наилучший способ избежать таких проблем и почему проблема не упомянута в документации?
Я добавляю пример кода:
Состояние:
export interface IAppState {
offersList: IOffer[],
}
Действия:
export enum OffersActions {
Get = '[Offer] Get',
GetSuccess = '[Offer] GetSuccess'
}
export const getOffers = createAction(
OffersActions .Get,
);
export const getOffersSuccess = createAction(
GetSuccess .GetSuccess,
props<{offersList: IOffer[]}>()
);
Редукторы:
export const offersReducer = createReducer(
[],
on(OffersActions.getOffersSuccess, (state, offers) => (offers.offersList))
);
Эффекты:
getOffers$ = createEffect(() => this.actions$.pipe(
ofType(getOffers),
mergeMap(() => this.offersService.SearchMany().pipe(
map(res => ({
type: OffersActions.GetSuccess,
offersList: res
}))
))
));
Селекторы:
const offers = (state: IAppState) => state.offersList;
export const selectOffers = createSelector(
offers ,
(state: IOffers[]) => state
);
export const selectOfferById = (id) => createSelector(
offer,
(state: IOffer[]) => state.find(x => x.id == id)
)
Использование (внутри компонента):
this.offer$ = this.store
.pipe(select(selectOfferById(this.route.snapshot.params.id)));
<offer-form
[offer]="offer$ | async">
</offer-form>
И теперь, если я изменю предложение внутри OfferFormComponent (например, внутри ввода), изменение применяется к магазину.
Также еще два вопроса:
Я добавил metaReducer storeFreeze из ngrx-store-freeze. Теперь я вижу, что объект, возвращаемый селектором, нельзя изменить - изменения во входных данных не применяются ни к объекту, ни к хранилищу.
- В storeFreeze README есть:
При возникновении мутации будет выдано исключение.
Почему я нев моей консоли нет исключений?
Я хочу выбрать какую-то часть магазина и поместить восстановленный объект в форму. Я хочу применить все изменения, чтобы сохранить, только если пользователь нажмет кнопку отправки. Таким образом, единственный способ сделать это - подписаться на выделение, скопировать результат, изменить клонированный объект и затем использовать редуктор? Например, вот так:
this.offers $ .subscribe (x => this.offers = JSON.parse (JSON.stringify (x)));