当嵌套在 '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>
);
}
这里,DetailPane
和 SideBar
都是包装在同名表示组件周围的容器组件。
在启动时(以及热重载期间),我使用此函数创建我的 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。
我正在尝试使用 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>
);
}
这里,DetailPane
和 SideBar
都是包装在同名表示组件周围的容器组件。
在启动时(以及热重载期间),我使用此函数创建我的 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。