React-redux connect()的mapStateToProps在react-router导航上被多次调用

问题描述 投票:12回答:2

我有一个简单的路由器(使用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} ; 它不是connect组件。

Pages组件是一个带有mapStateToProps()connect组件, 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
  };
}

然后当我加载页面或在帖子/页面路由之间切换时,我在console.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中间件,并且它没有报告任何状态更改或崩溃。 如果状态没有改变,为什么组件会多次渲染?

javascript reactjs react-router redux
2个回答
9
投票

根据react-redux经验,您不应该在mapStateToProps处理store属性,因为connect使用了对绑定存储属性的浅层检查来检查diff

要检查是否需要更新组件, react-redux调用mapStateToProps并检查结果的第一级属性。 如果其中一个更改( ===相等检查),组件将使用新的props更新。 在你的情况posts改变( map变换)每次mapStateToProps被调用,所以你的组件更新每家商店的变化!

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

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})
    };
  });
}

0
投票

Reselect允许您为派生状态处理创建memoized选择器函数。

Redux的文档以一个示例解释了如何使用它。 回购自述文件也有一个简单的例子。

© www.soinside.com 2019 - 2024. All rights reserved.