redux 中的选择器是什么?

IT技术 reactjs redux redux-saga
2021-05-04 00:52:18

我想按照这个代码redux-saga

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

然后像这样在传奇中使用

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个回答

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

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

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

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

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

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

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

等等...

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

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

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

为什么要使用它?

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

当相同的输入传递给函数时,使用reselect有助于记忆数据含义,返回先前的结果而不是再次重新计算。因此,这可以提高您的应用程序性能。

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、访问)运行重新渲染该组件,该组件只需要该商店的一部分 - 访问!

在 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/