Состояние Redux сбрасывается при обновлении окна (с клиентской стороны)
У меня есть очень большие и сложные объекты, такие как userInfo, chatInfo и т.д., Как в объектах & массивы с очень большой и вложенной информацией. Дело в том, что в моем приложении реакции каждый раз, когда я обновляю свою страницу, состояние избыточности сбрасывается, и мне приходится снова вызывать все эти API.
Я провел некоторые исследования на эту тему. Я проверил учебник Дэна Абрамова по редуксу. Что он делает, так это поддерживает состояние редукции в localStorage браузера и обновляет localStorage через каждые 100 или 500 мс. Я чувствую, как будто это запах кода.
Постоянно отслеживая состояние localStorage и обновляя его, это не повлияет на производительность браузера. Я имею в виду, что это не было одной из причин сбоя Angular 1, потому что он постоянно продолжал наблюдать за переменными состояния, и через некоторое время, если сайт продолжал работать в браузере, он просто замедлялся. Потому что наш скрипт постоянно проверял состояние переменных. я чувствую, как будто мы делаем то же самое здесь.
Если поддержание избыточного состояния в localStorage является правильным подходом, может кто-нибудь сказать мне, почему так? А если нет, то есть ли лучший подход?
Это не дубликат Как сохранить дерево избыточных состояний при обновлении?, потому что я спрашиваю совета, является ли постоянное состояние в локальном хранилище запахом кода или нет
Ответы
Ответ 1
Вопрос в том, в какой момент вам нужно добиться постоянства. Я чувствую, что ответ в вашем случае на перезагрузке страницы. Так что если вы беспокоитесь о производительности, я скажу:
* Обновлять localStorage только при изменении состояния. Внутри вашего редуктора при обновлении состояния.
* Читайте из localStorage при загрузке приложения.
(Таким образом, вы пишете только при изменении состояния и читаете только один раз)
Постскриптум
Я рекомендую пакет https://github.com/rt2zz/redux-persist для достижения постоянства в приложениях Redux.
Ответ 2
Я думаю, что использование localStorage
- ваш лучший вариант здесь, так как кажется, что данные, которые вы храните, нужны на клиенте. Если данные не изменяются, вам не нужно повторно запрашивать или смотреть localStorage
.
Еще одна вещь, которую вы можете сделать, - это обернуть closure вокруг вашего localStorage
, чтобы вы не всегда попадали в диск при извлечении ваши "большие" данные. Каждый браузер реализует localStorage
по-разному, поэтому нет никаких гарантий относительно последовательного поведения или производительности ввода-вывода.
Это также добавляет простой слой абстракции, который скрывает реализацию и контролирует все, что связано с вашими пользовательскими данными в одном месте.
Вот простой пример закрытия данных профиля пользователя:
// UserProfile.js
var UserProfile = (function() {
var userData = {};
var getUserData = function() {
if (!userData) {
userData = JSON.parse(localStorage.getItem("userData"));
}
return userData;
};
var setUserData = function(userData) {
localStorage.setItem("userData", JSON.stringify(userData));
userData = JSON.parse(localStorage.getItem("userData"));
};
return {
getUserData: getUserData,
setUserData: setUserData
}
})();
export default UserProfile;
Задайте объект данных пользователя: Это перезапишет localStorage
и установите локальную переменную в закрытии.
import UserProfile from '/UserProfile';
UserProfile.setUserData(newUserData);
Получить объект данных пользователя:. Это приведет к получению данных из локальной переменной в закрытии, иначе вы можете получить ее из localStorage
, если она не установлена.
import UserProfile from '/UserProfile';
var userData = UserProfile.getUserData();
Идея здесь состоит в том, чтобы загружать данные в память, начиная с localStorage
, при первом загрузке приложения или при первом вызове API. До тех пор, пока данные профиля пользователя не изменятся (например, пользователь обновит свой профиль, например), вы снова запросите API и снова обновите данные с помощью вызова UserProfile.setUserData(..)
.
Ответ 3
Я бы делал это только как слабый кеш и не полагался на него. Локальное хранилище ограничено (5 Мб на Chrome, например), и может быть недоступно. Вы должны тщательно проверить, что ваши данные были написаны.
Как говорили другие, вы не будете наблюдать за localStorage, который вы периодически будете промывать в магазине. Но я бы согласился с тем, что кажется довольно грубым взломом, чтобы слепо предположить, что все ваше государство было уместно продолжать в локальном хранилище. Как и во всех решениях для кеширования, вам необходимо внимательно изучить последствия (свежесть, истечение и т.д.). Похоже, вы можете сделать это постепенно - отберите несколько низко висящих кусочков фруктов, которые подходят для кеширования, и рассмотрите последствия кэширования, которые находятся в локальном хранилище.
Ответ 4
Попробуйте уменьшить-persist, вы можете делать оптимистичную настойчивость, агностик базовой платформы (веб/мобильный).
Если вы все еще считаете, что производительность является узким местом. Вы можете выполнить одно из следующих действий.
Cache Middleware
Создайте промежуточное программное обеспечение, которое прослушивает изменения и записывает их, но только очищает их каждые 5 секунд.
Прикрепите обработчик событий к window.beforeunload, чтобы обнаружить, что пользователь перемещается или закрывает браузер, чтобы сбросить изменения.
Стратегия сохранения
Чтобы сохранить данные, вы можете использовать одну из двух стратегий ниже.
- Храните его в локальном хранилище, если нет горлышка с производительностью.
- Отправьте JSON blob на сервер, например, с помощью загрузки файлов. Получить последнее состояние JSON, когда приложение загружается и сохраняется локально.
Я бы посоветовал вам начать с использования redux-persist. Если есть еще шея для бутылочки производительности, используйте промежуточное программное обеспечение кэш-памяти вместе с одной из двух стратегий сохранения.
Ответ 5
Я думаю, что в большинстве случаев вы хотите сохранить свое состояние в localStorage
после выполнения определенных действий. По крайней мере, это всегда имело место в проектах, в которых мне нужно было упорствовать.
Итак, если вы используете redux-saga
, redux-observable
или redux-cycles
для организации ваших побочных эффектов, вы можете легко сделать этот побочный эффект (сохраняя состояние в localStorage
), когда происходит одно из этих действий место. Я считаю, что гораздо лучший подход, чем "случайное" сохранение данных на основе интервала времени.
Ответ 6
Похоже, ваше понимание состояния просмотра заключается в том, что у вас есть промежуток времени, который будет проверять ваше состояние и обновлять его в localStorage. Тем не менее, я думаю, вы можете достичь этого же, обновив свой localStorage в методе жизненного цикла реагирования componentDidUpdate
. Этот метод будет срабатывать каждый раз при обновлении вашего компонента, чтобы вы могли его использовать и обновлять свой локальный хранилище каждый раз, когда он срабатывает, без каких-либо сбоев производительности.
Ответ 7
Один из вариантов - загрузить данные в INITIAL_STATE
window.__INITIAL_STATE__ = { ...state... }
и загрузите редуктор:
window.__APP_STATE__.__REDUCERS__.push(reducer)
Ответ 8
Совершенно нормально сохранять состояние в больших приложениях с уменьшением + реакции.
Относительно углового1, наблюдателей и циклов дайджестов, хотя при каждом изменении состояния, даже если вы rehydrate
заявили, что не все компоненты визуализированы из-за того, что refx connect API и vrtualDOM реагируют.
Вы можете проверить:
Производительность не должна быть вашей главной задачей. Если дело доходит до того, что нормализует ваше состояние и сохраняется только важная информация, например, черновики и т.д. (Меньше информации - меньше регидратации).
Большая проблема с такой настройкой обычно возникает, если в приложении есть какие-либо фоновые синхронизации или обновления сокетов. Наличие нескольких вкладок браузера приводит к тому, что асинхронная запись в локальную БД вызывает перезапись с предыдущими состояниями.
Вот тонкая оболочка поверх нее для перекрестной табуляции redux-persist-crosstab
Вы можете проверить некоторые из этих реализаций в mattermost webapp
и как они используют его для приложения реального времени.
Они просматривают некоторые обручи для дополнительной стабильности и производительности - ссылка для сохранения файла в самом важном webapp
Ответ 9
Я думаю, вы можете использовать модуль npm, называемый redux-storage. Он обеспечивает уровень сдерживания для redux с гибкими бэкэндами. Вы можете комбинировать хранилище redux с любым redux-storage-engine, который вы хотите. И, на мой взгляд, вы можете комбинировать это с redux-storage-engine-sessionstorage, предполагая, что вы хотите делиться и сохранять информацию до тех пор, пока браузер не будет открыт. Не нужно раздувать браузер с помощью localStorage. Для этого вам понадобится дополнительная поддержка javascript.
Redux-storage будет запускать загрузку и сохранять действия после каждого изменения состояния. Обеспечение большей гибкости в том, что делать в случае загрузки и сохранения. Также, если вы не сохраните некоторые изменения состояния, вы определяете массив состояния, от которого вы хотите отфильтровать.