Как технический руководитель в Holloway, я много думаю о программном обеспечении с теоретической точки зрения, иногда это может быть чистая философия или хардкорная алгебра. Во время собеседований по программной инженерии математические вопросы часто используются для проверки аналитических навыков. Но не только на собеседовании нужно мыслить математически. Я счел разумнее потратить несколько дней на обдумывание и анализ проблемы, прежде чем писать строку кода.

Несколько лет назад на собеседовании на должность инженера в Stripe у меня возник вопрос о создании хранилища данных, которое удаляет значения по истечении некоторого времени ожидания (или делает их недоступными). Это красивая головоломка, потому что ее можно решить множеством подходов, большинство из них будут работать, но только некоторые из них будут хорошими.

Головоломка нашла место в моей памяти между вещами, к которым я возвращаюсь время от времени, чтобы рефлексировать.

Внезапно я понял, что возможность устанавливать время жизни для записей в хранилище значений ключей (или не удалять их вообще) меняет способ организации и работы с такими вещами, как состояние хранилища redux. Например, мы можем забыть о перезаписи записей в состоянии хранилища.

Люди, которые работают с базами данных, вероятно, не поймут моего волнения. В БД нет такого понятия, как overwrite. Вы можете write, update или delete запись. Но состояние редукции - это немного другое.

Прежде всего, это клиентская сторона, а клиентские приложения сохраняют состояние, поэтому вам необходимо иметь состояние, описывающее, какие данные нужно отображать, и фактические данные, которые будут отображаться. Redux очень удобен, когда вам нужно где-то хранить подобные данные для вашего приложения.

Некоторое случайное todo-приложение может иметь такое состояние хранилища:

Очевидно, что нам нужно поместить все в магазин, чтобы описать, какое приложение может отображать в данный момент. И при необходимости извлекайте новые данные, разрешайте состояние маршрута, например, или загружайте данные, чтобы показать детали задачи внутри всплывающего окна.

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

Если приложению, использующему состояние из примера, потребуется получить дополнительные задачи в фоновом режиме, это приведет к их немедленной визуализации. Вероятно, это нежелательное поведение.

Отдельные данные и состояние

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

Это делает кеширование или предварительную выборку практически невозможным без взлома.

Наиболее идеальным решением, вероятно, было бы полное разделение данных и состояния и хранение записей данных где-нибудь в indexedDB и реализация чего-то вроде indexedDBConnect для предоставления данных компонентам React. Или придумайте другой способ. Но это более глубокая тема для погружения (Кстати, вот хорошая статья об indexedDB: Как использовать IndexedDB для создания прогрессивных веб-приложений), в этой статье я хочу поговорить о том, как redux store может быть организованным для лучшего хранения как состояния, так и данных.

Нам нужно отделить записи данных от состояния приложения. Звучит просто, но на усвоение нужно время. Я пытаюсь объяснить на примере.

Давайте возьмем состояние нашего приложения todo и выясним, что это за состояние, а что за запись.

  1. состояние маршрута:
route: { url: '/' }

routeэто состояние, и нет никаких записей. В нем указывается текущий URL и все.

2. состояние пользователя:

user: { id: "user-1", name: "Peter", },

user немного интереснее. Он объявляет, кто является текущим пользователем и какие поля у модели пользователя. Итак, здесь указано currentUser, а запись - userobject.

разделенное состояние и запись будут выглядеть так:

users: { 
  current: "user-1", 
  "user-1": { id: "user-1", name: "Peter" },
}

3. задачи:

tasks: {    
  list: [      
    {        
      id: "task-1", 
      title: "finish to-do app with a new framework",        
      state: "in-progress",      
     }, {        
      id: "task-2",        
      title: "write on medium about it",        
      state: "not-started",      
     },    
   ],  
}

Здесь указаны идентификаторы задач и порядок задач:

tasks: { 
  currentTasks: [
    "task-1",
    "task-2"
  ],
  
  "task-1": {        
    id: "task-1", 
    title: "finish to-do app with a new framework",        
    state: "in-progress",      
  }, 
  "task-2": {        
    id: "task-2",        
    title: "write on medium about it",        
    state: "not-started",      
  },
}

И все состояние редукции после реорганизации:

{
  route: { url: '/' },
  users: { 
    current: "user-1", 
    "user-1": { id: "user-1", name: "Peter" },
  },
  tasks: { 
    currentTasks: [
      "task-1",
      "task-2"
    ],
  
    "task-1": {        
      id: "task-1", 
      title: "finish to-do app with a new framework",        
      state: "in-progress",      
    }, 
    "task-2": {        
      id: "task-2",        
      title: "write on medium about it",        
      state: "not-started",      
    },
  },
}

Записи состояния и данных разделены. Мы можем предварительно получить столько записей задач, сколько нам нужно, или визуализировать подмножество задач, не удаляя записи задач. И нам не нужно беспокоиться о переполнении redux данными, мы можем удалить значения после, например, по таймауту. Зависит от того, как вы решите загадку с самого начала истории.

Заключение

Все это хорошо выглядит как в теории, так и на практике. В приложении для чтения Holloway есть резервный магазин, организованный таким образом. Он позволяет отображать более одного маршрута одновременно для функции всплывающих окон или предварительно загружать массивные объекты JSON перед визуализацией руководства, не беспокоясь о неправильном состоянии хранилища и многих других вещах, включая оптимизацию производительности, но это тема для будущего рассказа.