Reselect — это библиотека для запоминания значений, полученных из редукс-состояния, тем самым уменьшая дублирование вычислений и повышая производительность. Вычисление значения вне компонента позволяет нам избавиться от некоторого значения, которое используется только как параметр вычислительной функции, тем самым уменьшая повторный рендеринг избыточного компонента.

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

components/
  ComponentA/
    index.js
    selectors.js
  ComponentB/
    index.js
    selectors.js
...

В чем проблема?

Вскоре после того, как мы создали все больше и больше селекторов, мы обнаружили, что некоторым компонентам нужно значение, создаваемое одним и тем же селектором. Если бы мы сохранили структуру выше, мы могли бы написать такой код, как показано ниже.

// In ComponentC
// Aha! The selector that this component need is already in ComponentA. DRY!!!
import { selectSomething } from '@/components/componentA/selectors';

Однако этот стиль не имеет смысла. Вот недостатки:

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

Структура проекта, которую мы применили.

Нам нужна структура, по которой легко отличить, используется ли селектор многими компонентами и эпиками. Селекторы делятся на три типа по структуре, которую применила наша команда:

  • селектор редуктора: входные данные из одного редуктора, хранятся в определенной папке редуктора
  • селектор композиции: входные данные из нескольких редукторов, хранятся в корневой папке редуктора
  • селектор компонентов: выходные данные предназначены для определенного компонента, хранятся в папке определенного компонента

Структура проекта показана ниже. Обратите внимание, что мы используем redux-toolkit (слайсы, вы можете рассматривать его как редюсер) для повышения эффективности разработки, и это здорово!

src/
  components/
    ComponentA/
      index.js
      selectors.js  # component selector
    ComponentB/
      index.js
      selectors.js
    ...
  redux/
    slices/
      sliceA/
        index.js
        selectors.js  # reducer selector
      sliceB/
        index.js
        selectors.js
      ...
    selectors.js  # composition selector

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

  1. Проверьте селектор компонентов или селектор редукторов, существует ли уже подобный селектор.
  2. Если нет, и вы не уверены, будет ли он использоваться другим компонентом, не стесняйтесь создавать его как селектор компонентов. Вы можете переместить селектор на уровень редуктора при будущей разработке или проверке кода, так как его перемещение не требует больших усилий.

Вывод

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