乐闻世界logo
搜索文章和话题

What are selectors in redux

7 个月前提问
3 个月前修改
浏览次数81

5个答案

1
2
3
4
5

Redux 中的 selectors 是用来从 Redux 的状态树(state tree)中抽取并派生数据的函数。在 Redux 应用中,全局状态是以一个单一的对象存储的,由于这个状态树可以非常庞大并包含许多不同的数据片段,直接从中获取数据可能会既复杂又繁琐。Selectors 就是为了简化访问状态树中的数据而存在的。

Selectors 的主要职责和作用有:

  1. 封装状态结构:Selectors 提供了一个抽象层,允许组件不必了解状态树的具体结构即可读取状态。这意味着如果状态树的结构发生了变化,只需更新相应的 selectors,而无需修改所有使用了这部分状态的组件。

  2. 计算派生数据:Selectors 可以用来计算派生数据,即根据状态树中的原始数据来计算新的数据表示。比如,从一个包含多个对象的数组中过滤出符合特定条件的对象,或者计算某些数据的总和。

  3. 性能优化:配合库如 Reselect,selectors 可以通过记忆(memoization)技术避免不必要的计算。这意味着只有当 selector 的输入(即状态树的相关部分)发生变化时,selector 才重新计算,否则它会返回上一次计算的结果,从而提高应用的性能。

  4. 重用和组合:Selectors 可以被重用于不同的组件中,也可以组合在一起构建更复杂的 selectors,这有助于减少代码冗余并保持逻辑的一致性。

例子

假设我们有一个 Redux 状态,其中包含一个商品列表,每个商品都有价格和类别。如果我们想要获取所有电子类别商品的总价格,我们可以写一个 selector 来实现这一点:

javascript
// state结构示例 const state = { products: [ { id: 1, name: '手机', category: '电子', price: 599 }, { id: 2, name: '平板电脑', category: '电子', price: 799 }, { id: 3, name: '手表', category: '配饰', price: 199 } // 更多商品... ] }; // Selector const selectElectronicProductsTotalPrice = (state) => { return state.products .filter(product => product.category === '电子') .reduce((total, product) => total + product.price, 0); }; // 使用Selector const totalPrice = selectElectronicProductsTotalPrice(state); console.log(totalPrice); // 输出应为 1398

在这个例子中,selectElectronicProductsTotalPrice 是一个 selector,它首先过滤出所有电子类别的商品,然后计算并返回这些商品价格的总和。通过这种方式,我们不仅封装了对状态树的查询逻辑,还使得这段逻辑更易于测试和重用。

2024年6月29日 12:07 回复

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

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

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

2024年6月29日 12:07 回复

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

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

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

ETC...

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

2024年6月29日 12:07 回复

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

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

为什么要使用它?

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

使用重新选择有助于记住数据,这意味着当将相同的输入传递给函数时,返回之前的结果而不是再次重新计算。因此,这可以增强应用程序的性能。

2024年6月29日 12:07 回复

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

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

但你可以使用选择器

shell
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 的参数是输入选择器和一个将该选择器的结果转换为新选择器的结果的函数。例如

shell
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')) )

这相当于(忽略记忆):

shell
import {getProducts} from '../app/selectors' export const getProductTitles = (state) => { return getProducts(state).map((product) => product.get('title')) }

createSelector 函数可以组合来自多个选择器以及单个选择器的数据。我们可以将任意数量的选择器传递给 createSelector,它们的结果将传递给作为最终参数传递的函数。举一个(有点做作的)例子:

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

相当于

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

使用选择器编写 mapStateToProps 函数时的常见模式是返回一个对象,其中每个键存储特定选择器的结果。Reselect 中的 createStructuredSelector 辅助函数让我们可以用最少的样板代码编写此模式。例如,如果我们写

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

它相当于

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

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

2024年6月29日 12:07 回复

你的答案