繁体   English   中英

状态如何传递给 react-redux 应用程序中的选择器?

[英]How is state passed to selectors in a react-redux app?

我遇到了一个例子,其中 mapStateToProps 函数正在使用记忆化。 我只是想知道“状态”参数是如何传递到记忆选择器上的。 在查看 reselect 和 redux 的文档后,似乎 mapStateToProps 可以返回一个接受状态作为其参数的函数,并且连接装饰器可能是将状态传递给它的那个,但我不确定。 有人可以透露一些信息吗?

视图/曲目列表/index.js

const mapStateToProps = createSelector(
  getBrowserMedia,
  getPlayerIsPlaying,
  getPlayerTrackId,
  getCurrentTracklist,
  getTracksForCurrentTracklist,
  (media, isPlaying, playerTrackId, tracklist, tracks) => ({
    displayLoadingIndicator: tracklist.isPending || tracklist.hasNextPage,
    isMediaLarge: !!media.large,
    isPlaying,
    pause: audio.pause,
    pauseInfiniteScroll: tracklist.isPending || !tracklist.hasNextPage,
    play: audio.play,
    selectedTrackId: playerTrackId,
    tracklistId: tracklist.id,
    tracks
  })
);

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Tracklist);

核心/曲目列表/selectors.js

export function getCurrentTracklist(state) {
//  console.log(state);
  let tracklists = getTracklists(state);
  return tracklists.get(tracklists.get('currentTracklistId'));
}

export const getTracksForCurrentTracklist = createSelector(
  getCurrentPage,
  getCurrentTrackIds,
  getTracks,
  (currentPage, trackIds, tracks) => {
    return trackIds
      .slice(0, currentPage * TRACKS_PER_PAGE)
      .map(id => tracks.get(id));
  }
);

当我们使用 react-redux 中的 Connect 组件时,状态如何传递给选择器的概述

什么是选择器?

选择器从源中提取数据子集。

让我们将 Redux 存储视为我们的“前端数据库”。 出于目的在数据库中,如果您想提取执行查询的总数据的子集。 以类似的方式,选择器是我们对 Redux 存储的查询。

在最简单的情况下,选择器可以只返回整个商店的状态。

reselect 文档为我们提供了使用选择器的三个重要理由

  • 选择器可以计算派生数据,允许 Redux 存储尽可能少的状态。
  • 选择器是有效的。 除非其中一个参数发生变化,否则不会重新计算选择器。
  • 选择器是可组合的。 它们可以用作其他选择器的输入。

什么是高阶组件?

高阶组件是一个函数,它接受一个现有组件并返回一个新组件。

Connect 是一个高阶组件,它被赋予一个选择器

取自这个精彩的要点,它很好地解释了连接。

connect() 是一个将 Redux 相关的 props 注入到你的组件中的函数。

Connect 是一个高阶组件,它使我们的 React 组件了解 Redux 存储。 当我们调用 connect 时,我们可以传递 mapStateToProps 和 mapDispatchToProps。 这些函数定义,使我们新组件将被连接到了Redux专卖店的方式

我们可以通过将 mapStateToProps 函数作为参数传递给它访问状态。

我们还可以通过 mapDispatchToProps 将动作创建者绑定到 store.dispatch。 这样做的好处是我们不需要传递整个 store 以便组件可以访问 store.dispatch 以便组件可以调度自己的 Redux 操作。

我们传递给 Connect 的 mapStateToProps 函数是一个选择器

来自 react-redux 文档

mapStateToProps 函数接受整个 Redux 存储状态的单个参数,并返回一个对象作为 props 传递。 它通常被称为选择器。

将 mapStateToProps 返回的对象视为我们对 Redux 存储的查询结果。 所结果的

mapStateToProps 函数通常应该返回一个普通对象。

调用 mapStateToProps 的结果通常是一个普通对象,表示我们从 redux 存储中提取的数据。

高阶 Connect 组件允许我们通过将来自这个新对象的数据与组件现有的 props 合并来扩展现有组件的功能。

由于选择器只是函数,我们也可以使用 connect 组件将它们连接到 Redux 存储。

但是在某些情况下,我们可以返回一个函数。 我们为什么要这样做?

通过在 mapStateToProps 中返回一个函数,我们可以劫持组件的渲染周期并优化性能

在需要更多控制渲染性能的高级场景中,mapStateToProps() 也可以返回一个函数。 在这种情况下,该函数将用作特定组件实例的 mapStateToProps()。 这允许您进行每个实例的记忆。

通过将 mapStateToProps 函数作为参数传递给我们的高阶组件,我们的连接组件将在 Redux 存储中的某个状态发生更改时更新。

如果这些更新发生得非常频繁或者状态树很大,那么 reselect 库就很有用,因为它允许我们使用记忆化的选择器。

这个花哨的词意味着选择器调用的结果会被存储起来,以防需要再次检索。

因此,如果 mapStatesToProps 返回一个普通对象而不是一个函数,那么每当我们的商店状态发生变化时,我们就会为我们的组件提供新的道具。???

将选择器连接到商店

如果您使用的是 React Redux,您可以在 mapStateToProps() 中将选择器作为常规函数调用:

import { getVisibleTodos } from '../selectors'

const mapStateToProps = (state) => {
  return {
    todos: getVisibleTodos(state)
  }
}

跨多个组件共享选择器

在使用 reselect 库时,我们可以像组件一样提供 reselect selectors 道具。 这允许我们跨多个组件共享选择器。

假设我们有多个 toDo 列表,每个列表都有自己的 ID。 我们仍然会为每个 toDo 列表实例使用相同的 getVisibleTodos 选择器,但只是传递一个不同的 id 作为 prop。

然而,问题在于 createSelector 仅在其参数集与其前一组参数相同时才返回缓存值。

reselect 文档指出我们可以通过在 mapStateToProps 中返回一个函数来克服这个限制:

为了在多个组件之间共享一个选择器并保持记忆,组件的每个实例都需要它自己的选择器私有副本。 如果提供给 connect 的 mapStateToProps 参数返回一个函数而不是一个对象,它将用于为容器的每个实例创建一个单独的 mapStateToProps 函数。

通过在 mapStateToProps 中返回一个函数,我们可以克服这个限制,并且记忆将正常工作。

有关更详细的解释,请参阅

就是这么简单:举个例子,我有一个像这样的mapStateToProps

function mapStateToProps(state) {
  return {
    categoryHistory: getCategoryHistory(state,'extended')
  }
}

然后我创建了一个这样的选择器

export const getCategoryHistory = (state, type) => createSelector([getTaxonomy, selectedCategoryID], (categories, categoryID) => categories.getIn([type, categoryID]) || [])(state)

解决方案是调用createSelector()状态作为参数传递:

createSelector()(state)

在选择器中,您可以使用要传递的所有参数。

在您提到的情况下, mapStateToProps 是一个接受状态并返回对象的函数。 当您将 mapStateToProps 传递给 connect 时,您传递了一个函数,该函数接受 connect 提供的状态作为其参数。

createSelector 创建一个可以接收状态并返回对象的函数。 因此,您可以将其分配给 mapStateToProps 并将其传递给 connect。

在文档中,您通常会找到以下内容:

const mapStateToProps = (state) => {
    whatever code
}

export default connect(mapStateToProps, mapDispatchToProps)(Component)

其中 mapStateToProps 接受由 connect 提供的 state 参数。

但是,可以让 mapStateToProps 成为一个选择器,如下所示:

const mapStateToProps = createSelector(
    whatever code
)

这是因为 createSelector 可以采用如下状态:

createSelector(whatever code)(state)

并返回一个对象,就像你在文档中找到的 mapStateToProps 一样。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM