一种方法是将路由设置为指向同一个组件,并使用路由参数来设置当前选择的选项卡。通过这种方式,您可以实现您所追求的“静默”行为:
<Route path="/dashboard" component={App}/>
<Route path="/news/:itemId" component={App}/>
和:
componentWillReceiveProps() {
const { route, params } = props;
const { path } = route;
const selectedTab = path !== '/dashboard' ? 1 : 2;
this.setState({selectedTab})
console.log('news item -> ', params.itemId)
}
第二种方法是保存滚动位置并重新设置。
一个工作的 JSBin:https://jsbin.com/qiraqa/edit?js,output
相关代码:
scroll(e) {
const { tab, scrollPositions } = this.state;
const target = e.target,
scrollTop = target.scrollTop;
scrollPositions[tab] = scrollTop;
this.setState({
scrollPositions
});
console.log(scrollTop);
}
navigateToTab(tab) {
const { scrollPositions = [] } = this.state,
scrollPosition = scrollPositions[tab] || 0;
this._container.scrollTop = scrollPosition;
this.setState({tab});
}
和:
<div style={MainStyles.overflow} onScroll={this.scroll.bind(this)} ref={(c) => this._container = c}>...
这样,您可以使用 localStorage 或 redux store 来持久化 scrollPositions 数组,并在路由更改后再次加载它。
请注意,此示例与 React Tabs 恕我直言无关,问题在于保存两个导航状态之间的滚动位置。
更多信息
标签组件,无论是react-tabs 还是material-ui's tabs,通过呈现所有标签并在您在标签之间移动时打开和关闭可见性来保持滚动位置。它将 Tab 的样式设置为 {height: 0, overflow: hidden} 并且通过这种方式使容器在其滚动位置时保持活动状态。
正如您所提到的,这在您更改根组件时不起作用,当组件重新加载时滚动位置将重置。这可能是正确的行为,因为路由无法预先知道路由更改的副作用。
引用 this relevant Github thread 的 Dan Abramov 的话:
...由您决定以相同的方式渲染组件。例如,如果您不在本地缓存数据,则路由器无法恢复您的位置。但这也是浏览器默认行为的工作原理,我们只是试图模仿它
换句话说,根据这个范例,这不是路由器的责任,应该手动完成。