redux 中的选择器是什么?

What are selectors in redux?

我正在尝试在 redux-saga

中关注这个 code
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 是一个 reducer,以及它如何与 redux-saga 相适应?

getUser不是reducer,它确实是一个selector,也就是一个知道如何从store中提取特定数据的函数。

Selectors 提供了一个额外的层,这样如果你改变了你的商店结构并且突然之间你的 users 不再是 state.entities.users 而是在 state.users.objects.entities(或其他)处,您只需要更新 getUser 选择器,而不是应用程序中您引用旧位置的每个地方。

这使得它们在重构 Redux 存储时特别方便。

选择器是 redux 状态的吸气剂。与 getter 一样,选择器封装了状态的结构,并且是可重用的。选择器还可以计算派生属性。

你可以写选择器,比如你在redux-saga中看到的那些。例如:

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

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

等...

您还可以使用 reselect,这是一个简单的 Redux “选择器”库,它可以记忆选择器以提高它们的效率。

选择器是将 Redux 状态作为参数和 return 一些数据传递给组件的函数。

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

为什么要使用它?

  1. 其中一个主要原因是为了避免 Redux 中的重复数据。
  2. 您的数据对象形状会随着应用程序的增长而不断变化,因此与其对所有相关 component.It 进行更改,不如 recommended/easier 在一处更改数据。
  3. 选择器应该靠近减速器,因为它们在相同的状态下运行。数据更容易保持同步。

使用 reselect 有助于在将相同的输入传递给函数时记住数据含义,return 是先前的结果而不是重新计算 again.So,这会提高您的应用程序性能。

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)
    }
}

主要问题是此组件使用所有用户:state.user 并且用户中的任何更改(等 isAdmin、isAuth、access)运行重新呈现此组件,它只需要此存储的一部分 - 访问!!!

In Redux, whenever an action is called anywhere in the application, all mounted & connected components call their mapStateToProps function. This is why Reselect is awesome. It will just return the memoized result if nothing has changed.

In the real world, you will most likely need the same certain part of your state object in multiple components.

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

Reselect提供的createSelector函数实现了从之前的选择器派生选择器的最基本方式。最简单的用例是从单个其他选择器派生选择器。在这种情况下,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 函数时的常见模式是 return 一个对象,每个键存储特定选择器的结果。 Reselect 中的 createStructuredSelector 辅助函数让我们可以使用最少的样板文件编写此模式。例如,如果我们写

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/