当嵌套在 'smart' Redux 容器组件下时,React 路由不会自动更新

React routes not automatically updating when nested under 'smart' Redux container components

我正在尝试使用 React、React-router 和 Redux 创建一个 Electron 应用程序。我发现的是,当我将 switch/route 逻辑嵌套在纯表示组件 (Page) 下时,我的路由逻辑工作得非常好,但我不得不刷新页面才能看到如果嵌套在 'smart' 容器组件下,导航会发生变化。

在我的 React 组件层次结构的顶部附近(在 HashRouter 下方)我有一个 Page:

export default function Page (props) {
  return (
      <div className={`${styles.page}`}>
        <SideBar/>
        <DetailPane>{props.children}</DetailPane>
      </div>
  );
}

这里,DetailPaneSideBar 都是包装在同名表示组件周围的容器组件。

在启动时(以及热重载期间),我使用此函数创建我的 React 层次结构:

export default () => (
    <Router>
      <Page>
        <Switch>
          <Route exact path='/txDefinitions/:definitionName/:fieldName' component={FieldPage}/>
          <Route exact path='/txDefinitions/:definitionName?' component={DefinitionPage}/>
          <Route exact path='/rxDefinitions/:definitionName?' component={DefinitionPage}/>
          <Route exact path='/'/>
          <Route component={Route404}/>
        </Switch>
      </Page>
    </Router>

这意味着 <Switch>...</Switch> 嵌套在 <DetailPane> 之下。

如果我尝试在我的应用程序中导航(单击侧栏中的链接),在我强制重新加载 Electron 应用程序之前,我不会真正看到详细信息窗格呈现新组件。

但是,我发现如果我从 Page:

中省略 DetailPane,路由会按预期工作
export default function Page (props) {
  return (
      <div className={`${styles.page}`}>
        <SideBar/>
        {props.children}
      </div>
  );
}

这是我的 React 层次结构 没有 DetailPane(工作正常):

这是我的 React 层次结构 with DetailPane(不正确):

(很抱歉使用图片,但我不确定是否有办法从 React devtools 复制到剪贴板 - 如果在新选项卡中打开会显得更大)。


当我写这个问题时,我意识到这对我来说不是什么大问题,因为早期的重构已经使 DetailPane 的 'smart' 版本明显过时了。使用 DetailPane 的纯演示版本 而是解决了这个问题:

import * as React from 'react';
//import {DetailPane} from '../../containers'; // Smart/Redux
import {DetailPane} from '../../components'; // Dumb/presentational
import {SideBar} from '../../containers/';
const styles = require('./Page.scss');

export default function Page (props) {
  return (
      <div className={`${styles.page}`}>
        <SideBar/>
        <DetailPane>{props.children}</DetailPane>
      </div>
  );
}

不过,我还是很好奇为什么这对容器组件版本不起作用。作为参考,这是 DetailPane:

的容器组件版本
import {connect} from 'react-redux';
import {DetailPane} from '../../components';

// TODO: delete this container?

function mapStateToProps (state): {} {
  return {};
}

function mapDispatchToProps (dispatch) {
  // TODO.
  return {};
}

export default connect(mapStateToProps, mapDispatchToProps)(DetailPane);

connect HOC 实现了 shouldComponentUpdate 逻辑,因此如果 props 不改变,组件就不会更新。

要防止这种情况发生并始终呈现组件,您可以覆盖 connect 调用中的 pure 选项。

export default connect(mapStateToProps, mapDispatchToProps, undefined, { pure: false })(DetailPane);

有关详细信息,请参阅 react-redux API docs