Комментарии 16
Смена формата данных - очень распространённая ошибка. Особенно при использовании redux-persist. Часто бывает поменяли структуру хранилища, потом это прилетает на клиент и там сразу всё ломается так, что вообще ничего нельзя сделать. Юзер обновляет страницу - ничего не меняется. А как очистить localStorage абсолютное большинство юзеров не имеет понятия. Особенно на мобиле.
Как делать правильно? Нужно версионировать хранилище или его части (слайсы). Вместо того, чтобы просто менять структуру, нужно создать новый слайс, а в редьюсере предусмотреть выставление значения по умолчанию путём конвертации старого значения в новый формат.
Если подойти к вопросу серьезно, то дело уже попахивает миграциями. Но я все таки пришел к выводу что если состояние стораджа нельзя безболезненно выкинуть и пересоздать заново, то в 95% кейсов мы выбрали неправильный инструмент (за исключением всякой offline-first экзотики)
Тот способ решения, что я описал, по сути и есть миграция. Выкинуть значение - это в принципе ок, но выкинуть подразумевает, что нужно перестать использовать старый ключ и создать новый. В противном случае получим всё ту же ошибку вроде cannot read property of undefined, и всё опять станет раком. А если вы собираетесь для выкидывания старого значения писать код с проверкой формата значения и удалять его, если формат старый, то это уже и есть миграция, пусть и упрощённая.
Миграцией я все таки называю преобразование старых форматов в свежий с сохранением данных (возможно, формально я не прав). Так я один раз упарывался, не понравилось, тк нарастает большая борода конвертаций которые умеют кушать все-все исторические форматы.
Раз мы всегда умеем работать с кейсом "в сторадже пусто", то проще свести кейс "кривые данные" к нему небольшой валидацией. Если это попадает в ваш концепт миграции, то можем называть это так =)
Преобразование старого формата в пустое значение - это тоже преобразование)) Суть миграции в том, что это некий код, который запускается один раз для того, чтобы что-то сделать с данными.
А вот валидация, в отличие от миграции, выполняется каждый раз при обращении к данным. Если валидация простая, то ок, а если нет, тут уже надо смотреть. Кроме того, старые миграции можно со временем дропать, а в валидациях потом поди разбери через год, что проверка нужна была для покрытия разового кейса, а не постоянно.
А не является ли более правильным вариантом использовать indexDB? Есть версионность, разные приложения можно разнести по разным базам.
Зависит от кейса, но по дефолту скорее нет чем да — там замороченное (и довольно мерзкое) асинхронное апи + технология менее популярная. Для offline-first приложения попробовать стоит, для настроек / баннеров / кеша лучше не надо.
Мне такой подход нравится больше, хоть он и немного сложнее.
теперь нет - сейчас Storage вместо этого всего
Я пошëл по относительно простому пути. Данные из localStorage перед восстановлением кастуются через yup — так если схема больше не соответствует данным у юзера в локалСторадже — они будут удалены либо модифицированы в соответствии со схемой.
Хм… А не будет проблем с отсутствием поддержки localStorage на устройстве? Есть вот такая обёртка, проверяющая доступ: https://github.com/etiennea/storage-factory
Вряд ли стоит об этом сильно переживать, там очень хорошая поддержка https://caniuse.com/?search=localstorage
Насколько я понимаю, тут не в поддержке вопрос, а в настройках приватности. Т.е. кто-то может просто запретить сохранять какие-либо данные у себя.
Когда я приступал к статье, у меня было смутное воспоминание что в приватном режиме сафари localStorage отключен, но к счастью эту фичу убрали еще в сафари 11
Кейс с явным полным отключением localStorage точно нишевый уровня "пользователь отключил js" и покрывается фолбеком аналогично SSR (единственное отличие — в firefox при этом localStorage === null, а не is not defined)
Спасибо, хороший пойнт!
Все ваши примеры - это как не надо программировать.
И речь даже не о localStorage, а о ненадежном программировании.
Стреляем себе в ногу из localStorage