Pull to refresh

Comments 8

Набор рекомендий довольно странный и даже спорный. Аргументации не хватает, опять же.

  1. Рекомендация не хранить состояние в системе, предназначенной для управления состоянием. Ну, такое. Кроме того - если у нас асинхронный код (загрузка данных) в эффекте, то каким еще образом компоненту узнать о состоянии это загрузки.

  2. Ок

  3. Изменение вложенных объектов - к каким проблемам с отслеживанием изменений это приводит? Мы же, конечно, не говорим про прямую мутацию объектов в стейте (`state.a = newValue`), что нарушает основное правило редьюсера?

  4. Не очень понятно, о чем речь. С примером было бы лучше :)

  5. А что за проблемы с редиректом в эффекте? И где тогда делать редирект?

  6. id в fetch - звучит как очень специфический рецепт для специфической задачи. Например, в подавляющем большинстве наших задач switchMap в эффекте отлично справляется с отменой, никаких айди не надо.

  7. Для SSR надо быть осторожней не только с интервалам, но и таймаутами. И не только в эффектах, а вообще во всем приложении. Ничего redux-специфичного тут нет. А помимо части про SSR, рекомендация звучит как "не использовать интервал, потому что он генерит длинную последовательность событий". Как бы его используют исключильно тогда, когда нам нужно сгенерить такую последовательность. Опять же, неважно эффект это или нет.

  1. Там я скорее про то, что если хранить состояния в стейте, то приходится писать много однотипного кода.

    Разберу на примере загрузки.

    Происходит dispatch события load. В reducer для экшена load, свойство loading приравнивается true, затем если успешно загрузили вызываем loadSuccess и меняем loading на false, иначе вызываем loadFailure и делаем loading равным false.

    Для того чтобы получить данные из стейта нужно будет создать селекторы. Затем в компоненте подписаться на конкретный селектор.

    Все выше описанное можно схлопнуть в одну подписку на loadSuccess$ , где loadSuccess$ это actions.pipe(ofType(loadSuccess)). И тогда не нужно будет менять reducer, не нужно создавать селекторы.

    Конечно, иногда есть смысл хранить состояния в стейте, но в большинстве случаем это избыточно.

  2. Хорошо

  3. Я имел ввиду, что конструкции вида { ...state, myObject: {...state.myObject, tags: [...state.myObject.tags, ...other]} } усложняют читабельность и перегружают мутацию. Что не нужно в редьюсере делать сложные вычесления и желательно в редьюсере выполнять только простые операции - заменить объект новым, поменять статус флага.

  4. Это когда свойствами state являются другие state - { state1: { loading: boolean}, state2: { changing: boolean} }.

  5. Проще объяснить на примере. Клиент кликает оплатить товар и после этого, клиента нужно перенаправить на внешний платежный ресурс. Однако клиент не дожидаясь этого уходит на другую страницу. Если редирект сделать в эффекте, то клиент уходя со страницы увидит новую страницу, а потом будет перенаправлен на платежную систему. Если бы редирект был в компоненте, то тогда запрос на перенаправление был бы прерван и клиент уходя из "корзины", дальше бы продолжил свои действия.

  6. Согласен.

  7. Да, возможно я связал две не связанные вещи.

  1. loadSuccess$ - это вы сильно упростили. Все равно же нужно состояние, а не событие (допустим, чтобы показывать/скрывать спиннер в шаблоне). Таким образом, это превратится во что-то типа

public loading: boolean
...
actions$.pipe(
  ofType(loadSuccess, loadFailure),
  takeUntil(this.onDestroy)
).subscribe(() => {
  this.loading = false;
  this.changeDetectorRef.markForCheck()
})

Что довольно-таки до фига кода, когда задача была "избавиться от бойлерплейта".

Кроме того, так компонент больше завязан на детали эффекта. Возможно, вам в этом случае вообще не нужен эффект? Фетчим данные прямо из компонента, затем диспатчим результат в стор.

  1. Да, модифицировать вложенные структуры - боль. Я тоже старюсь придерживаться плоского стейта по возможности. Если это частый случай, то что-то вроде https://immerjs.github.io/immer/ должно помочь сделать это более читаемым.

  2. Если речь про вложенные редьюсеры - то почему это плохо? Если же все делается одним редьюсером, то это в копилку предыдущего пункта про вложенные изменения.

  3. Эта же логика справедлива для любых сайд эффектов. не только редиректа, разве нет? Отписываемся, где надо. Согласен, что в случае именно с редиректом эффект для пользоваля более заметен, чем когда мы, скажем, просто продолжаем загружать данные в фоне и запихивать в стор, хотя юзер уже ушел на другую страницу.

  1. Если loading будет в state, то в компоненте будет подписка на селектор. Но это уже вкусовщина.

  1. Это не плохо. Просто ненужное усложнение.

  2. Да, все так.

Если флаг загрузки в state, то в комоненте async pipe. Вручную никто подписку не делает, когда у нас есть реактивный стейт

Я вообще миновал стадию с использованием классического redux/ngxs/ngrx увидев в соседнем проекте во что это превратилось спустя год. Сказал ну его нафиг и взял акиту чтобы просто иметь четкую точку истины и этого вполне хватило + разработчиков обучать не надо было раскапывать портянку нечитаемого rxjs кода.
Сейчас в новых проектах в основном использую elf, потому что даже бойлеплейт акиты стал надоедать, но думаю уже над тем чтобы и от него отказаться.

Судя по документации, да даже и по примерам в этой статье, Akita как-то принциально не отличается от NgRx. Буду благодарен, если вы поделитесь опытом из первых рук :).

Субъективно, разницы большой нет. Конечно, ngrx почаще можно встретить. В крупных проектах, как правило, нету redux.

Sign up to leave a comment.

Articles