Javascript 在react redux应用程序中,状态如何传递给选择器?

Javascript 在react redux应用程序中,状态如何传递给选择器?,javascript,reactjs,redux,reselect,Javascript,Reactjs,Redux,Reselect,我遇到了一个示例,其中mapStateToProps函数正在使用memonization。我只是想知道“state”参数是如何传递给记忆选择器的。在查看了重新选择和redux的文档之后,似乎mapStateToProps可以返回一个接受状态作为参数的函数,而connect decorator可能是将状态传递给它的函数,但不确定。谁能帮我弄点光吗 视图/tracklist/index.js const mapStateToProps = createSelector( getBrowserMe

我遇到了一个示例,其中mapStateToProps函数正在使用memonization。我只是想知道“state”参数是如何传递给记忆选择器的。在查看了重新选择和redux的文档之后,似乎mapStateToProps可以返回一个接受状态作为参数的函数,而connect decorator可能是将状态传递给它的函数,但不确定。谁能帮我弄点光吗

视图/tracklist/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);
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));
  }
);
core/tracklist/selectors.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);
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商店的查询

在最简单的情况下,选择器只能返回整个存储的状态

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

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);
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));
  }
);
  • 选择器可以计算派生数据,允许Redux存储 最小可能状态
  • 选择器是高效的。选择器不可用 除非其中一个参数发生更改,否则将重新计算
  • 选择器是 可组合。它们可以用作其他选择器的输入
什么是高阶组件?

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

Connect是一个高阶组件,可为其提供选择器

摘自精辟的要点,它很好地解释了连接

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

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

我们可以通过将mapStateToProps函数作为参数传递给它来访问state

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

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

从react redux文档

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

考虑mapStateToProps返回的对象,该对象是我们对Redux存储的查询结果。结果

mapStateToProps函数通常应返回普通对象

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

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

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

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

通过重新使用MapStateTops中的函数,我们可以劫持组件的渲染周期并优化性能

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

通过将mapstateTrops函数作为参数传递给我们的高阶组件,只要Redux存储中的某些状态发生更改,我们连接的组件就会被更新

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

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

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

将选择器连接到商店

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

跨多个组件共享选择器

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);
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));
  }
);
在使用重选库时,我们可以像组件一样提供重选选择器道具。这使我们能够跨多个组件共享选择器

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

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

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

import { getVisibleTodos } from '../selectors'

const mapStateToProps = (state) => {
  return {
    todos: getVisibleTodos(state)
  }
}
为了在多个组件之间共享选择器并保留 记忆化,组件的每个实例 需要选择器自己的私有副本。 如果为connect提供的mapStateToProps参数返回函数 它将用于创建单个对象,而不是对象 MapStateTops函数用于容器的每个实例

通过在MapStateTops中返回一个函数,我们可以克服这个限制,并且可以实现记忆