Подтвердить что ты не робот

Что такое селектор в редуксе?

Я пытаюсь следовать этому code в redux-saga

export const getUser = (state, login) => state.entities.users[login]
export const getRepo = (state, fullName) => state.entities.repos[fullName]

который затем используется в саге как this:

import { getUser } from '../reducers/selectors'

// load user unless it is cached
function* loadUser(login, requiredFields) {
  const user = yield select(getUser, login)
  if (!user || requiredFields.some(key => !user.hasOwnProperty(key))) {
    yield call(fetchUser, login)
  }
}

Этот редуктор getUser (это даже редуктор) очень сильно отличается от того, что я обычно ожидал бы, чтобы редуктор выглядел.

Может ли кто-нибудь объяснить, что такое селектор, и как getUser является редуктором и как он вписывается в редукс-сагу?

4b9b3361

Ответ 1

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

Селекторы предоставляют дополнительный слой, так что если вы изменили структуру своего магазина, и внезапно ваш users больше не находился в state.entities.users, а вместо этого в state.users.objects.entities (или что-то еще) вам нужно только обновить getUser и не везде, где вы делаете ссылку на старое местоположение.

Это делает их особенно удобными, когда речь идет о реорганизации вашего магазина Redux.

Ответ 2

Селекторы - это геттеры для состояния редукции. Как и геттеры, селекторы инкапсулируют структуру состояния и могут повторно использоваться. Селекторы также могут вычислять производные свойства.

Вы можете записывать селектора, например, те, которые вы видели в саге. Например:

const getUsersNumber = ({ users }) => users.length;

const getUsersIds = ({ users }) => users.map(({ id }) => id);

и т.д...

Вы также можете использовать reselect, который представляет собой простую "селекторную" библиотеку для Redux, которая memoize selectors делает их более эффективными.

Ответ 3

Селекторы - это функции, которые принимают состояние Redux в качестве аргумента и возвращают некоторые данные для передачи компоненту.

const getUserData = state => state.user.data;

Зачем его использовать?

  1. Одна из главных причин - избегать дублирования данных в Redux.
  2. Форма вашего объекта данных постоянно меняется по мере роста вашего приложения, поэтому вместо внесения изменений во все связанные компоненты. Настоятельно рекомендуется/проще изменить данные в одном месте.
  3. Селекторы должны находиться рядом с редукторами, поскольку они работают в одном и том же состоянии. Данные легче синхронизировать.

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

Ответ 4

function mapStateToProps (state) {
    return {
        user: state.user,
    }
}

initialState of reducer by user store
const initialState = {
  isAdmin:false,
  isAuth:false,
  access:[1,2,5]
};

class AppComp extends React.Component{
render(){
        const {user: { access:access}} = this.props;
        const rand = Math.floor(Math.random()*4000)
        return (<div>
            {'APP ${rand} '}
    <input type="button" defaultValue="change auth" onClick={this.onChangeUserAuth} />
        <p>TOTAL STATUS COUNT IS {access.length}</p>
        </div>)
    }
}}

но вы можете использовать селектор

var getUser = function(state) {
    return state.user
}


const getAuthProp = createSelector(
    getUser,
    (user) => user.access
);


function mapStateToProps (state) {
    return {
       // user: state.user,
        access: getAuthProp(state)
    }
}

Основная проблема заключается в том, что этот компонент использует все user: state.user и любые изменения в пользователе (и т.д. IsAdmin, isAuth, access) запускает повторное рендеринг этого компонента, которому требуется только часть этого хранилища - доступ !!!

В Redux всякий раз, когда в приложении вызывается действие, все подключенные и подключенные компоненты вызывают свою функцию mapStateToProps. Вот почему Реселект это круто. Он просто вернет запомненный результат, если ничего не изменилось.

В реальном мире вам, скорее всего, понадобится одна и та же определенная часть вашего объекта состояния в нескольких компонентах.

https://medium.com/@parkerdan/react-reselect-and-redux-b34017f8194c

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

var getProducts = function(state) {
    return state.products
}


import {getProducts} from '../app/selectors'
import {createSelector} from 'reselect'

export const getProductTitles = createSelector(
    getProducts,
    (products) => products.map((product) => product.get('title'))
)

Это эквивалентно (игнорированию запоминания):

import {getProducts} from '../app/selectors'

export const getProductTitles = (state) => {
    return getProducts(state).map((product) => product.get('title'))
}

Функция createSelector может объединять данные из нескольких селекторов, а также из одного селектора. Мы можем передать любое количество селекторов в createSelector, и их результаты будут переданы функции, переданной в качестве последнего аргумента. Для (несколько надуманного) примера:

const isInCheckout = createSelector(
    getIsShippingPage,
    getIsBillingPage,
    getIsConfirmationPage,
    (isShipping, isBilling, isConfirmation) =>
        isShipping || isBilling || isConfirmation
)

эквивалентно

const isInCheckout = (state) => {
    return (
        getIsShippingPage(state) ||
        getIsBilingPage(state) ||
        getIsConfirmationPage(state)
    )
}

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

const mapStateToProps = createStructuredSelector({
    title: getProductTitle,
    price: getProductPrice,
    image: getProductImage
})

это эквивалентно

const mapStateToProps = (state) => {
    return {
        title: getProductTitle(state),
        price: getProductPrice(state),
        image: getProductImage(state)
    }
}

https://docs.mobify.com/progressive-web/0.15.0/guides/reselect/