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

时间:2017-01-10 13:37:09

标签: javascript reactjs redux reselect

我遇到了一个示例,其中mapStateToProps函数正在使用memoization。我只是想知道如何将“state”参数传递给memoized选择器。在查看重新选择以及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));
  }
);

3 个答案:

答案 0 :(得分:23)

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

什么是选择器?

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

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

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

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

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

什么是高阶组件?

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

Connect是一个提供选择器的高阶组件

取自this精彩的要点,给出了连接的良好解释。

  

connect()是一个将Redux相关的道具注入你的   成分

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

我们可以通过传递mapStateToProps函数作为参数来授予它访问状态的权限。

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

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

来自react-redux docs

  

mapStateToProps函数接受整个的一个参数   Redux商店的状态并返回一个要作为道具传递的对象。它是   通常称为选择器。

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

  

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

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

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

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

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

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

  

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

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

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

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

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

将选择器连接到商店

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

import { getVisibleTodos } from '../selectors'

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

分享多个组件的选择器

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

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

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

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

  

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

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

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

答案 1 :(得分: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)

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

答案 2 :(得分:0)

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

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

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

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

export default connect(mapStateToProps, mapDispatchToProps)(Component)

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

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

const mapStateToProps = createSelector(
    whatever code
)

这是因为createSelector可以处于如下状态:

createSelector(whatever code)(state)

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