【问题标题】:What are selectors in redux?redux 中的选择器是什么?
【发布时间】:2016-12-05 01:53:48
【问题描述】:

我正在尝试在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 的?

【问题讨论】:

  • Dan Abramov 的这个视频涵盖了他在定义选择器时使用的动机和约定,至少在制作这个视频时是这样。 egghead.io/lessons/…

标签: reactjs redux redux-saga


【解决方案1】:

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

选择器 提供了一个附加层,这样如果您更改了商店结构并且突然之间您的 users 不再位于 state.entities.users 而是位于 state.users.objects.entities(或其他),那么您只需要更新 getUser 选择器,而不是应用中您引用旧位置的每个位置。

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

【讨论】:

  • 称其为“选择器”是含糊的,难道他们不能找到一个更好的自我记录名称吗?就像商店访问封装器一样。
  • @shinzou 上帝,我很感谢他们没有选择“商店访问封装器”
【解决方案2】:

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

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

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

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

等等……

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

【讨论】:

    【解决方案3】:

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

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

    为什么要使用它?

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

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

    【讨论】:

      【解决方案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)
          }
      }
      

      主要问题是该组件使用所有用户:state.user 和用户的任何更改(等 isAdmin ,isAuth,访问)运行重新渲染此组件,它只需要此存储的一部分 - 访问!!!

      在 Redux 中,每当在应用程序的任何地方调用一个操作时, 所有已安装和连接的组件都调用它们的 mapStateToProps 功能。这就是重新选择很棒的原因。它只会返回 如果没有任何变化,则记忆结果。

      在现实世界中,您很可能需要相同的特定部分 多个组件中的状态对象。

      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/

      【讨论】:

        猜你喜欢
        • 2022-07-21
        • 1970-01-01
        • 2010-09-06
        • 1970-01-01
        • 2012-07-05
        • 2016-12-12
        • 1970-01-01
        • 1970-01-01
        • 2013-05-01
        相关资源
        最近更新 更多