Представим, что у нас есть приложение React / Redux для бронирования мест на рейс. Каждое сиденье - это объект, который выглядит примерно так:
{id: 1, seatClass: "business", cost: 300, availability: "available"}
Все места хранятся в нашем состоянии Redux: state.seats.allSeats
, которое представляет собой массив объектов сидений. Когда пользователь бронирует место на рейс, идентификатор этого места сохраняется в state.auth.user.reservation
. Так что, если бы мы хотели показать детали бронирования места для нашего текущего пользователя, вошедшего в систему? Мы могли бы сделать что-то подобное в mapStateToProps
:
const mapStateToProps = (state) => { state.seats.allSeats.find(seat => { return seat.id === state.auth.user.reservation } }
Это полностью сработает, но использование такой логики в mapStateToProps считается плохой практикой. Если бы нам нужно было снова отобразить эту информацию, нам пришлось бы скопировать и вставить этот код, и это совсем не СУХОЙ. Итак, куда мы должны его положить? В функции селектора.
Вам может быть интересно, что такое селекторная функция на данный момент - отличный вопрос. Селекторная функция вычисляет производные данные и позволяет Redux сохранять минимально возможное состояние. Другими словами, он использует логику вычислений для хранения только той части состояния, которая вам нужна. Если вы все еще очень запутались, я полностью понимаю. Так было и со мной. По сути, селекторы берут одну или несколько частей состояния Redux, производят какие-то вычисления, а затем возвращают вычисленную часть состояния - так же, как это делает наш mapStateToProps
выше. Но вместо этого мы удаляем логику из mapStateToProps в отдельную функцию - наш селектор. Это выглядит почти идентично нашей функции сверху:
const selectUserSeat = (state) => { state.seats.allSeats.find(seat => { return seat.id === state.auth.user.reservation } }
Здорово! Теперь, если нам снова понадобится информация о месте пользователя, мы можем просто передать этот селектор в mapStateToProps
.
const mapStateToProps = (state) => { return {reservedUserSeat: selectUserSeat(state)} }
Оптимизация селекторов с помощью повторного выбора
Важно отметить, что функции селектора пересчитывают данные при каждом вызове. Если вы читали мои последние блоги, возможно, вы знаете, как мы можем этого избежать - мемоизация. Если вам нужно вспомнить, что такое мемоизация, ознакомьтесь с моим блогом, указанным ниже:
Объяснение запоминания с использованием JavaScript
Я думаю, что каждый программист слышал это слово раньше и подумал:« запоминание ? Мемоизация - это не совсем так, но… medium.com »
Войдите в библиотеку Reselect, которая полностью позаботится о запоминании. Он работает, принимая определенные части состояния, необходимые для ваших вычислений, и до тех пор, пока эти части состояния не изменяются, он будет возвращать кешированную версию ваших данных, а не пересчитывать.
Давайте рассмотрим простой пример использования Reselect. Мы можем установить его, используя простой yarn add reselect
или npm install reselect
. Затем мы используем функцию createSelector
Reselect, которая принимает части состояния, которые будут использоваться в вычислениях, в качестве первого аргумента (ов) (если есть 2 отдельных части состояния, которые нас интересуют, они будут первыми двумя аргументами. функции), а последним аргументом будет функция, которая выполняет вычисление с использованием этих частей состояния и возвращает производные данные. Обещаю, это не так сложно, как кажется. Давайте посмотрим на это здесь:
// First, we grab the pieces of state we're concerned with const seatList = (state) => state.seats.allSeats const reservedSeat = (state) => state.auth.user.reservation // Then, we plug them into the createSelector function as the first // arguments. The last argument will be a function that makes our // calculation and spits out the data we want. const selectedUserSeat = createSelector( seatList, reservedSeat, (allSeats, reservation) => { return allSeats.find(seat => seat.id === reservation) } )
Теперь ваша селекторная функция будет пересчитывать только при изменении state.seats.allSeats
или state.auth.user.reservation
. В противном случае он просто вернет запомненное значение!
Теперь, когда вы знаете основы функций селектора, вы готовы повысить уровень своей организации и оптимизации в приложении Redux. Если вы хотите узнать больше о селекторах в целом или глубже изучить то, что предлагает Reselect, я привел ссылки на некоторые ресурсы ниже, которые были для меня особенно полезны. Удачи!