我正在开发一个 React 应用程序,其中使用了 React-router。我遇到一个问题,我正在更改路线,更改反映在 URL 中,但安装的组件没有更改。这是组件,它是我的主要容器组件之一:
class AppContent extends Component {
state = {
isStarted: false
};
componentDidMount = async () => {
try {
await this.props.checkIsScanning();
this.setState({ isStarted: true });
}
catch (ex) {
this.props.showErrorAlert(ex.message);
}
};
componentWillUpdate(nextProps) {
if (nextProps.history.location.pathname !== '/' && !nextProps.isScanning) {
this.props.history.push('/');
}
}
render() {
return (
<div>
<VideoNavbar />
{
this.state.isStarted &&
<Container>
<Row>
<Col xs={{ size: 8, offset: 2 }}>
<Alert />
</Col>
</Row>
<Switch>
<Route
path="/scanning"
exact
render={ (props) => (
<Scanning
{ ...props }
isScanning={ this.props.isScanning }
checkIsScanning={ this.props.checkIsScanning }
/>
) }
/>
<Route path="/"
exact
render={ (props) => (
<VideoListLayout
{ ...props }
isScanning={ this.props.isScanning }
/>
) }
/>
</Switch>
</Container>
}
</div>
);
}
}
const mapStateToProps = (state) => ({
isScanning: state.scanning.isScanning
});
const mapDispatchToProps = (dispatch) => bindActionCreators({
checkIsScanning,
showErrorAlert
}, dispatch);
export default connect(mapStateToProps, mapDispatchToProps)(withRouter(AppContent));
所以,让我们关注重要的事情。有一个 Redux 属性 isScanning,它对于此处的行为至关重要。默认情况下,当我打开应用程序时,路由为“/”,VideoListLayout 组件显示正常。从那里,我单击一个按钮开始扫描,这会将路径更改为“/scanning”,并显示扫描组件。扫描组件除其他外,定期调用服务器来检查扫描是否完成。完成后,它将“isScanning”设置为 false。当 AppContent 重新渲染时,如果“isScanning”为 false,它会将“/”推送到历史记录中,将用户送回主页。
这里几乎所有东西都可以工作。当我开始扫描时,扫描组件就会出现,并且它会很好地轮询服务器。扫描完成后,redux 会正确更新,因此“isScanning”现在为 false。 AppContent 中的 componentWillUpdate() 函数正常工作,并且成功将“/”推送到历史记录中。 URL从“/scanning”变为“/”,因此路由正在改变。
但是,Scanning 组件仍处于安装状态,而 VideoListLayout 组件则未安装。我不明白为什么会发生这种情况。我本以为一旦路线改变,组件也会改变。接下来我可以尝试什么?
我很确定您遇到了react-router文档中描述的这个问题,其中react-redux的shouldComponentUpdate阻止您的组件在路由更改时重新渲染:https://reacttraining.com/react-router/core /guides/redux-integration/blocked-updates。这绝对是一个痛苦且令人困惑的事情!
一般来说,React Router 和 Redux 工作得很好 一起。但有时,应用程序可能有一个组件 位置更改时不会更新(子路线或活动导航 链接不会更新)。如果出现以下情况,就会发生这种情况: 组件连接到 通过 connect()(Comp) 进行 redux。该组件不是“路由组件”, 意味着它不是这样渲染的:问题是 Redux 实现了 shouldComponentUpdate 并且没有任何迹象表明有任何内容 如果没有从路由器接收到 props,则会发生变化。这是 很容易修复。找到连接组件并包装的位置 它在 withRouter 中。
所以在你的情况下,你只需要交换 connect 和 withRouter 的顺序:
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(AppContent));