Один и тот же магазин на нескольких компонентах - PullRequest
0 голосов
/ 31 октября 2019

в моем приложении у меня есть user.component и college.component. В user.component с store я получаю список пользователей

this.store.dispatch(new LoadUsers());
this.users$ = this.store.select(UserSelector.getAllUsers)
this.users$.subscribe(...)

И на college.component Мне также нужен этот пользователь из магазина, и я вызываю ту же рассылку

this.store.dispatch(new LoadUsers());
this.users$ = this.store.select(UserSelector.getAllUsers)
this.users$.subscribe(...)

Я звонюто же самое this.store.dispatch(new LoadUsers());, потому что, если я на первой странице загружаю открытую страницу колледжа, у меня нет пользователей в магазине, и мне нужно вызвать их.

Если я впервые открываю users.component, я получаю пользователей, нокогда я после перехода на страницу колледжа я получаю ошибку

Невозможно прочитать свойство 'данные' неопределенного для пользователей.

Каков наилучший способ обработки хранилища в этом случаенравится?

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

Thnx

Ответы [ 2 ]

2 голосов
/ 31 октября 2019

Если ваши пользовательские данные сильно меняются, можно перезагрузить. Если ваши пользовательские данные довольно статичны, как это обычно бывает, нецелесообразно совершать этот вызов несколько раз, потому что это просто делает ваше приложение медленным без причины.

Чтобы справиться с одиночной загрузкой, есть два способа:Делать это. вы должны сохранить загруженный параметр в вашей сущности, а затем при успешной загрузке установить для этого загруженного значения значение true в редукторе.

Теперь вы можете подписаться на это загруженное значение, если оно ложно, отправлять нагрузку, если оно истинно,Не отправляй звонок. Этот маршрут упрощает эффекты, но ваши контейнеры будут иметь более длинный / более уродливый код.

constructor(private store: Store<fromAuth.State & fromData.State>){
  this.users$ = this.store.select(UserSelector.getAllUsers);
}


ngOnInit() {
  this.store.select(UserSelector.getUsersLoaded).subscribe(value => 
    if (!value) this.store.dispatch(new LoadUsers());
  );
}

Более плавный способ - сохранить код как есть и выполнить эту проверку в эффекте. (ответил мне Дунканом Хантером о курсе Pluralsights на ngrx) ( Ссылка на курс ngrx по Pluralsight )

  1. Загрузка компонентов и подписка на магазинпеременная, в которой данные могут быть или будут.
  2. Отправляет действие в ngOnInit для загрузки данных.
  3. При проверке эффекта проверяется, есть ли в хранилище данные, и, возможно, если оно старше определенного времени,Я стараюсь изо всех сил проверять действующее хранилище как можно меньше, так как это делает их более сложными, но в реальных проектах у меня часто бывает 6-12 подобных эффектов.
  4. Если нет данных или устаревший вызов http, чтобы загрузитьно если он уже загружен, я отправляю действие типа {type: 'entityXLoadedFromStore'};Который ничего не делает, кроме добавления сообщения системы в систему, чтобы увидеть, что оно было загружено из магазина.

Этот маршрут обеспечивает чистоту кода в контейнерах, но усложняет эффекты.

Оба маршрута жизнеспособны, вы можете выбрать тот, который вы предпочитаете.

Я бы хотел сослаться на приложение фантастическое демо , предоставленное командой NGRX, котороеявляется отличным источником вдохновения для методов ngrx. (Однако они не обращаются к вашему вопросу там).

0 голосов
/ 31 октября 2019

Какой смысл использовать хранилище, если вы делаете вызов API дважды для одной и той же сущности?

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

Для этого я бы рекомендовал добавить loaded и loading два новых поля в вашем штате, а затем создатьселектор isInitialised, например:

export const getUsersInitialised = (state: State) => state.loaded || state.loading;

, затем загружать пользователей, только если пользователи не загружены или какой-либо другой компонент уже загружает их, например,

getUsers(): Observable<User[]> {
  const users = this.store.select(getAllUsers);

  this.store.select(getUsersInitialised).pipe(take(1), filter(v => !v)).subscribe(() => {
    this.store.dispatch(new LoadUsers());
  });

  return users;
}

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

NOTE -

  • Изначально загрузка и загрузка будет ложной.
  • Обязательно обновите пользователя в магазине, если вы редактируете пользователя из внешнего интерфейса.
  • В действии LoadUsers убедитесь, что вы изменили состояние пользователей loading на true
  • В ответе API выполнитеобязательно измените загруженное состояние пользователей на true и состояние загрузки до false.
...