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


我有一个简单的路由器(从 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} 有一些导航;它不是 connected组件。

Pages组件是一个 connected组件 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 路线变化多次被叫?

另外,为什么这么简单 map 功能 mapStateToProps 导致它在Posts容器中第三次被调用?

我正在使用基本的 logger 和 crashReporter 来自Redux文档的中间件,它没有报告任何状态更改或崩溃。如果状态没有改变,为什么组件会多次渲染?


7872
2017-11-06 18:22


起源

对此有任何更新,任何机会? - João Cunha
老实说,没有。我开始删除不同的东西,看看有什么可能触发它。我只是再看一遍,看起来像是Redux的 @@INIT 动作会再次触发它,但很难记录该动作。在服务器上呈现时,它只记录一个 mapStateToProps 每个容器。希望得到@DanAbramov的回答 - Mike
我还查看了Redux真实世界的例子,看看mapStateToProps在那里被调用了多少次,它收集了大量的调用。我认为只要你使用像这样的工具,它就不那么重要了 重新选择 记住你的选择器。 - Mike
最后一点:在更改路线时(使用react-router)我也只能获得一个 mapStateToProps 每个容器。从本质上讲,它现在仅在页面加载时被多次调用。 - Mike
这事有进一步更新吗?我也有同样的问题!任何输入都会有所帮助! - Raathigesh


答案:


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

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


0
2018-01-08 09:48



我很久以前就解决了这个问题,但是接受这个答案,因为Reselect是一个很棒的库。 - Mike


通过经验 react-redux,你不应该在里面处理商店属性 mapStateToProps 因为 connect 使用浅层检查绑定存储属性来检查diff

要检查您的组件是否需要更新, react-redux 电话 mapStateToProps 并检查结果的第一级属性。如果其中一个改变了=== 等式检查),组件将使用新的道具进行更新。在你的情况下 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})
    };
  });
}

9
2018-03-18 10:37



看起来你的github链接已经死了....你指的是这条线吗? github.com/reactjs/react-redux/blob/... - sfletche
确实,代码 connect.js 已经移动和改变了很多,谢谢@sfletche通知!注意 connect 似乎现在接受自定义更新条件,因此OP实际上可以实际调整它们(即使我建议不要改变任何内容 mapStateToProps 但在组件内的最后一刻) - blint