redux中的选择器是什么?

时间:2016-07-30 12:55:12

标签: reactjs redux redux-saga

我想在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是一个减速器以及它如何适应redux-saga?

4 个答案:

答案 0 :(得分:58)

getUser不是reducer,它确实是一个选择器,也就是说,一个知道如何从商店中提取特定数据的函数。

选择器提供了一个额外的图层,如果您更改了商店结构,并且您的users不再是state.entities.users,而是state.users.objects.entities (或者其他什么)那么你只需要更新getUser选择器,而不是你应用程序中每个地方都要更新旧位置。

这使得它们在重构Redux商店时特别方便。

答案 1 :(得分:12)

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

您可以编写选择器,例如您在redux-saga中看到的选择器。例如:

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

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

等...

你也可以使用reselect,它是Redux的一个简单的“选择器”库,可以记住选择器以提高它们的效率。

答案 2 :(得分:1)

选择器是将Redux状态作为参数并返回一些数据以传递给组件的函数。

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

为什么要使用它?

  1. 主要原因之一是避免Redux中的重复数据。
  2. 您的数据对象形状随着应用程序的增长而变化,因此不是在所有相关组件中进行更改。建议/更容易在一个地方更改数据。
  3. 选择器应该靠近减速器,因为它们在相同的状态下运行。数据更容易保持同步。
  4. 使用reselect有助于记忆数据,这意味着当相同的输入传递给函数时,返回先前的结果而不是重新计算。因此,这可以提高应用程序的性能。

答案 3 :(得分:1)

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)都会重新呈现此组件,而该组件仅需要该存储的一部分-访问!!!

  

在Redux中,每当在应用程序中的任何地方调用操作时,   所有已安装和连接的组件均调用其mapStateToProps   功能。这就是为什么Reselect很棒。它只会返回   记忆的结果,如果没有任何变化。

     

在现实世界中,您很可能需要   您的状态对象有多个组成部分。

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函数时的

常见模式是返回一个对象,每个键都存储特定选择器的结果。 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/

相关问题