Java Script

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

Если вы создаёте приложение с помощью React и Redux, от использования селекторов вы только выиграете.

Как выглядят селекторы? 

Перед тем как мы разберемся, почему селекторы удобны и как их использовать, давайте посмотрим, как приложение выглядит без них. Я создал необходимый минимум — базовую установку Redux:

  • У нас есть rootreducer, содержащий все данные о наших животных: 
const initialState = {
  data: [
    {
      name: "Milton",
      type: "cat",
      age: 4
    },
    {
      name: "Sammy",
      type: "dog",
      age: 2
    },
    {
      name: "Joseph",
      type: "turtle",
      age: 34
    },
    {
      name: "Simon",
      type: "dog",
      age: 8
    }
  ]
};
export default (state = initialState, action) => {
  switch (action.type) {
    default: {
      return { ...state };
    }
  }
};
  • Наш rootreducer передается в хранилище, хранилище передается в <Provider>.
  • В итоге PetsContainer.js подключается к хранилищу, выбирает животных, находит всех собак и выводит данные на экран. 

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

Выбор состояния из хранилища, фильтрация и поиск всех собак

Заметили что-нибудь странное? Фильтрация происходит внутри обратного вызова useSelector. Если мы сделаем так более одного раза, приложение сильно замедлится, не говоря уже о том, что это не самый красивый кусок кода. Если вы уже знакомы с Redux, вы знаете, что у нас есть редьюсеры для изменения и хранения состояния, действия для запуска триггеров изменения состояния. И третий кусочек пазла — селектор. Селекторы прекрасно дополняют картину, так как нам нужен эффективный способ получить данные из хранилища и отобразить их. 

Заметьте: здесь мы используем React-хуки в сочетании с Redux. 

Добавление библиотеки Reselect 

Reselect — это простая библиотека селекторов для Redux и не только, вдохновленная геттерами в NuclearJS, подписками в re-frame и этим предложением от speedskater.

Страница Reselect на GitHub 

Вот почему стоит использовать селекторы с React и Redux приложениями:

  • Селекторы могут просчитать производные данные, позволяя Redux сохранять минимальное возможное состояние. 
  • Селекторы эффективны — селектор не пересчитывается, пока один из его аргументов не изменится. 
  • Селекторы пригодны для компоновки — они могут использоваться внутри других селекторов. 

Установка библиотеки Reselect 

Установка библиотеки reselect очень проста — установите ее как любой пакет NPM:

yarn add reselect

Библиотека у нас есть, теперь давайте создадим новый файл под названием selectors.js — это файл, в котором хранится вся логика селекторов. Далее из библиотеки reselect импортируем метод createSelector:

import { createSelector } from "reselect";

Прекрасно! Теперь у нас есть доступ к методу createSelector.

Создание селектора

Селекторы очень просто понять. createSelector принимает столько аргументов, сколько вы захотите. Ключевой момент в том, что последний аргумент используется для фильтрации или выбора. Скажем, мы хотим выбрать всех собак. Вот что мы передаем селекторам:

  • Передаем всех питомцев селектору в качестве первого аргумента — это зависимости. 
  • Последний аргумент — всегда обратный вызов, с аргументами в качестве зависимостей, переданных ранее. 

Вот как выглядит код:

import { createSelector } from "reselect";
const selectAllPets = state => state.pets.data;
export const selectAllDogs = createSelector(
  selectAllPets,
  allPets => allPets
);

Теперь, если мы вернемся к PetsContainer, мы сможем импортировать селектор selectAllDogs и передать его redux-хуку useSelector:

Передача селектора хуку useSelector

Заметьте, что сейчас возвращаются данные всех питомцев. Это именно то, что мы делаем с помощью селектора. Чтобы получить данные всех собак, нам нужно применить логику фильтра внутри селектора: 

Применение логики фильтра внутри селектора

Теперь у нас все собаки. Вместо того, чтобы фильтровать внутри компонента, мы просто отображаем всех собак. Это отличный способ снизить нагрузку на компоненты. Помните, компоненты React хороши для рендеринга разметки, все остальное стоит исполнять в другом месте, чтобы уменьшить количество спагетти-кода и разделить задачи. 

Мы даже можем передавать селекторы в качестве аргументов другим селекторам. Как же нам выбрать всех собак и кошек в хранилище? 

Передаем селекторы как горячую картошку
  • Сначала мы получаем всех питомцев. 
  • Затем фильтруем всех собак и кошек. 
  • И объединяем их в один селектор, передавая селекторы в качестве аргументов. 
Отображение данных собак и кошек

Вот и все — приятные и простые компоненты React. Помните, результаты селектора хранятся в памяти и всегда возвращают тот же результат, пока результаты остаются неизменны. Это колоссально увеличивает производительность. 

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

Читайте также:


Перевод статьи Indrek Lasn: Increase your React + Redux Application Performance With the Reselect Library