#ngrx #ngrx-entity
#ngrx #ngrx-сущность
Вопрос:
У меня есть EntityState, скажем, типа Model
: EntityState<Model>
.
У меня есть API, который возвращает список частичных моделей. Partial<Model>[]
.
Я хочу обновить этот список. Для объектов, которые уже присутствуют в состоянии хранилища / объекта (конечно, по идентификатору), я хочу обновить все существующие свойства.
Для объектов, которых нет, я хотел бы обнулить отсутствующие поля и добавить эти объекты.
Каков наилучший способ добиться этого? Документация о том, как именно работают методы адаптера, довольно скудна (https://ngrx.io/guide/entity/adapter#adapter-collection-methods ).
upsert
требует Model[]
, не принимает Partial<Model>[]
, хотя в документации подразумевается, что он каким-то образом поддерживает частичные обновления.
add
Методы не указывают, что они делают для существующих совпадений идентификаторов … предположительно, они игнорируют новые элементы и не добавляют / заменяют?
update
Методы не указывают, что произойдет, если указанный идентификатор отсутствует.
Я думаю, что лучше всего было бы позвонить addMany
, а затем updateMany
, чтобы получить желаемое поведение, но, похоже upsert
, оно предназначено для этой цели. Проблема, вероятно, заключается в отображении этих Partial<Model>
типов в Model
экземпляры, которые отсутствуют в состоянии объекта … т. е. обнуление отсутствующих полей для новых записей.
Мысли / советы? Спасибо!
Ответ №1:
На данный момент это мое решение, если я не услышу о лучшем варианте от кого-то, кто лучше знает сущности ngrx.
interface IModel {
id: string;
}
export function upsertMany<TApiType extends IModel, TStoreModel>(
adapter: EntityAdapter<TStoreModel>,
models: TApiType[],
addMap: ((model: TApiType) => TStoreModel),
updateMap: ((model: TApiType) => Partial<TStoreModel>),
state: EntityState<TStoreModel>,
): EntityState<TStoreModel> {
state = adapter.updateMany(models.map(model => ({
id: model.id,
changes: updateMap(model),
})), state);
return adapter.addMany(models.map(addMap), state);
}
Комментарии:
1. Это решение, вероятно, в два раза дороже обычного, потому что мы дважды сопоставляем все объекты api и пытаемся добавить каждый, а затем обновить каждый независимо.
Ответ №2:
А как насчет этого:
on(MyActions.partialUpdate, (state, action) => {
return {
...state,
courses: adapter.upsertMany(action.partialCourses.map(c => {
let course = state.courses.entities[c.id] !== undefined ?
{ ...state.courses.entities[c.id] } :
new Course();
course.someProperty = c.someProperty;
return course;
}), state.courses)
}
})