Состояние 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 будет запускать загрузку и сохранять действия после каждого изменения состояния. Обеспечение большей гибкости в том, что делать в случае загрузки и сохранения. Также, если вы не сохраните некоторые изменения состояния, вы определяете массив состояния, от которого вы хотите отфильтровать.