React redux connect()'s的mapStateToProps在react路由器导航上被多次调用

React-redux connect()'s mapStateToProps being called multiple times on react-router navigation

本文关键字:导航 路由器 react 调用 mapStateToProps connect redux React      更新时间:2023-09-26

我有一个简单的路由器(从redux-router开始,切换到react-router以消除变量)。

<Router history={history}>
  <Route component={Admin} path='/admin'>
    <Route component={Pages} path='pages'/>
    <Route component={Posts} path='posts'/>
  </Route>
</Router>

管理组件基本上只是带有一些导航的{this.props.children};它不是CCD_ 4-ed组件。

Pages组件是connect ed组件,mapStateToProps()类似于

function mapStateToProps (state) {
  return {
    pages: state.entities.pages
  };
}

帖子更有趣:

function mapStateToProps (state) {
  let posts = map(state.entities.posts, post => {
    return {
      ...post,
      author: findWhere(state.entities.users, {_id: post.author})
    };
  }
  return {
    posts
  };
}

然后,当我加载页面或在Posts/Pages路由之间切换时,我会在控制台中得到以下内容。log().

// react-router navigate to /posts
Admin render()
posts: map state to props
Posts render()
posts: map state to props
Posts render()
posts: map state to props
// react-router navigate to /pages
Admin render()
pages: map state to props
Pages render()
pages: map state to props

所以我的问题是:为什么mapStateToProps在路线更改时被多次调用?

此外,为什么mapStateToProps中的一个简单map函数会导致它在Posts容器中被第三次调用?

我使用的是Redux文档中的基本loggercrashReporter中间件,它没有报告任何状态更改或崩溃。如果状态没有改变,为什么组件要多次渲染?

根据react-redux的经验,您不应该在mapStateToProps内部处理存储属性,因为connect使用绑定存储属性的浅层检查来检查差异。

为了检查组件是否需要更新,react-redux调用mapStateToProps并检查结果的一级属性。如果其中一个发生了更改(===相等性检查),则组件将使用新道具进行更新。在您的情况下,每次调用mapStateToProps时,posts都会发生更改(map转换),因此每次商店更改时都会更新您的组件!

您的解决方案是只返回商店属性的直接引用:

function mapStateToProps (state) {
  return {
    posts: state.entities.posts,
    users: state.entities.users
  };
}

然后在您的组件中,您可以定义一个按需处理数据的功能:

getPostsWithAuthor() {
  const { posts, users } = this.props;
  return map(posts, post => {
    return {
      ...post,
      author: findWhere(users, {_id: post.author})
    };
  });
}

Reselect允许您创建用于派生状态处理的记忆选择器函数。

Redux的文档举例说明了如何使用它。repo的自述文件也有一个快速的例子。