9

我遇到了一个示例,其中 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);

核心/tracklists/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));
  }
);
4

3 回答 3

26

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

什么是选择器?

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

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

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

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

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

什么是高阶组件?

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

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

摘自这个出色的要点,它很好地解释了连接。

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

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

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

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

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

来自 react-redux 文档

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

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

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

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

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

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

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

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

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

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

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

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

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

将选择器连接到商店

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

import { getVisibleTodos } from '../selectors'

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

跨多个组件共享选择器

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

假设我们有多个 toDo 列表,每个列表都有自己的 ID。我们仍然会为每个待办事项列表实例使用相同的 getVisibleTodos 选择器,但只需传递不同的 id 作为道具。

但是,问题在于 createSelector 仅在其参数集与其先前的参数集相同时才返回缓存值。

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

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

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

有关更详细的说明,请参阅

于 2017-01-10T21:49:16.083 回答
2

就是这么简单:让我们举个例子,我有一个这样的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)

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

于 2017-11-30T16:48:34.550 回答
0

在您提到的情况下, 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 所做的那样。

于 2020-02-15T06:09:20.467 回答