Нужно ли помещать в стор все состояния компонента?
Друзья,
Какие состояния нужно отражать в сторе?
Допустим есть компонент, который выгружает список постов и отрисовывает их в виде списка. Можно хранить только список постов, а можно пойти дальше, и все состояния UI (состояние загрузки, начало загрузки, прогресс загрузки, и так далее) тоже передавать в стор, для полного понимания что происходит. Многие доки именно это и описывают, и еще и передают ошибки в стор.
Какие данные вы обычно храните в сторе, если данные грузятся асинхронно, и могут быть различные ошибки?
Что храните локально, а что в сторе?
Может быть я что-то не понимаю, потому что у меня в голове стор это хранилище данных, а в доках в него передают в том числе и временные значения.
Тогда, может быть вы можете обьяснить, какой мотив делать так (?): https://redux.js.org/advanced/async-actions
Они в стор передают isFetching, didInvalidate, которые по сути временные значения на период загрузки данных или ввода пользователя.
Не понимаю мотивацию хранения этого в сторе. Если они перезагрузят страницу, всё это накроется, потому что запросы нужно заново отправлять, и стор будет со сломанными данными.
Они пишут:
>For every list of items, you'll want to store isFetching to show a spinner, didInvalidate so you can later toggle it when the data is stale, lastUpdated so you know when it was fetched the last time, and the items themselves. In a real app, you'll also want to store pagination state like fetchedPageCount and nextPageUrl."
Роман Якимчук, мотивация хранения в сторе каких-то вещей может быть в том, что они могут использоваться не в одном месте. И чтобы не заводить 15 локальных стейтов, или не заводить на самом верху один и пробрасывать его через все дерево, можно хранить в сторе
Да, и поэтому у меня и вызывают вопросы многочисленные доки, где хранят намного больше данных, временных.
Может быть есть кто так делает (хранит локальные значения в сторе), и может обяснить для примера, зачем они это делают.
Роман Якимчук, ну например состояние pending\loading может храниться для того, чтобы показывать пользователю спиннер. Спиннер расположен поверх всего, блокирует формы ввода\кнопки, чтобы пользователь ничего не натыкал. Или состояние формы - в случае, если форма отправляется, блокируем форму, чтобы пользователь не отправил еще одну вслед (пустую) или там не получил кучу ошибок валидации. Чем не вариант?
Роман Якимчук, к примеру есть redux-form, хорошая библиотека, которая нужна для управления состоянием форм.
в ней все автоматически работает, при инициализации формы в стор добавляются все поля форм, валидатовы и прочие конфиги. Когда мы выходим из страницы с формой, то весь объект с формой приводится к изначальному виду.
Часто возникает ситуации, когда приходится выполнять работу с формой из вне, к примеру автозаполнять данные после запроса на получение данных, генерировать новые элементы формы находу в зависимости от ранее выбранных значений, меять состояние на ходу и в этом всем есть смысл для выноса данных из локального стейта в глобальный стор.
cocomuffin, в таком случае страница, допустим, будет перезагружена посреди загрузки, и получим что данных в стопе нет, спиннер будет виден, а запрос вовсе не отправлен, и спиннер будет крутиться бесконечно.
Получается надо отслеживать такие кейсы, а это лишняя головная боль. Опираясь только на данные без состояний, пользователь бы увидел что данных нет и началась бы новая загрузка данных.
Кода меньше, сложности меньше, сценариев для обработки меньше, значений в сторе меньше.
Роман Якимчук,можно все вообще положить в компоненты - даже стор не нужен, кода меньше, и дальше по вашему тексту.
Да, эти описанные кейсы пропадут и не будут мучать. Только вот придется начать отслеживать другие кейсы и уже для них городить огород.
Правильное решение как всегда - в грамотном разделении в конкретном приложении в зависимости от задач, структуры, сценариев использования и так далее.
Состояния компонента кладете в стейт компонента, состояния данных - в стор.
Скорее всего источник вашего смущения в том что вы думаете что состояния загрузки данных - это состояние компонента, а это не так, это как раз относится к данным - данных нет, данные загружаются, данные загружены, данные загружены с ошибкой - это все не про UI. То что они "временные"ничего не значит. Информация о том что в происходит загрузка данных - это тоже данные.
Это может вообще не показываться в UI или же показываться сразу во многих компонентах - не важно.
UI просто может отображать эти состояния каким-то образом, так же как он отображает данные когда они в сторе появляются.
Здесь весьма тонкая граница. Если стор предназначен для хранения данных, вместе с данными хранить флаг того, что данные сейчас в процессе получения, а ещё при изменениях стора этот стейт к примеру сбрасывается в локалсторадж, и вдруг на бэке "что-то пошло не так", пользователь, уставший от ожидания конца спиннера перезагружается страницу, и опять ловит тот же самый спиннер. К примеру это "что-то не то" легко лечится повторно попыткой загрузки, но здесь этого не получится.
Всё же такое состояние как загрузка - это состояние не данных, а компонента, который визуализирует этот процесс, вернее самого процесса. Путем логических размышлений получаем то, что после выполнения перезагрузки страницы, процесс загрузки данных ещё не запущен, да и в холодном хранилище об этом нет ничего.
Граница тут толстенная как китайская стена и прозрачная .
Если вы все состояние приложения сбрасываете в локалсторадж одним куском в любой момент времени, то можно и не таких проблем поиметь.
После выполнения перезагрузки страницы у вас и данные не грузятся, и никакого флага о том что они загружаются в сторе не должно быть. Если по факту данные у вас не грузятся а в стейте стоит флаг что они грузятся - это просто неправильно работающее приложение, которое надо починить.
К правильному разделению стейта это имеет косвенное отношение.
Даже если у вас вообще UI нет и белая страница (утрирую чтобы было понятно что это не стейт какого-то компонента) - загрузка данных, обработка состояния, ошибок, правильная работа при перезагрузке страницы - все это остается так же актуально.
Стор предназначен для хранения состояния приложения. В это состояние входят как данные, так и различные системные необходимости, например, текущий роут (если мы связываем роутинг с Redux) или сессия пользователя. Индикатор загрузки сюда тоже класть. При этом глобальный индикатор будет показывать лоадер, к примеру, оверлеем над всем приложением.
А вот в случаях, когда нужно положить в стор что-то локальное, например, при сабмите формы нужно переключить ее состояние; тогда пользуйтесь стейтом компонента. В случаях, когда один и тот же стейт требуют несколько компонентов (но не все приложение), можно извращаться по-разному. Мы в проекте на flux просто делали приватные сторы, которые шарились между соседними компонентами, и избегали расшаривания стейта между не соседствующими компонентами. Когда стор один, как в redux, можно использовать HOC, наследование или написать собственный хук.