React Router Push Silently

React Router Push Silently

本文关键字:Silently Push Router React      更新时间:2023-09-26

在我的例子中,我有几个选项卡。标签容器可以被滑动。如果用户切换选项卡,路由也会更新。例如:

如果user在表1中,则路由为/home。当他滑动到Tab 2时,路线将是/home/news。当滑动到Tab 3时,路由变为/home/about,以此类推。

我知道this.props.push(NEXTROUTE)可以实现。但是通过这种方式,组件被重新渲染,使我失去了前一个选项卡的最后滚动位置。我的案例需要保持标签的最后滚动位置,而不是滚动到顶部。

是否有可能在反应路由器中推送状态silently ?我不希望组件在push状态时被重新渲染,这样我就可以保持屏幕的最后滚动位置。

任何想法吗?谢谢。

一种方法是将路由设置为指向同一个组件,并使用路由参数来设置当前选择的选项卡。这样你就实现了你想要的"沉默"行为:

<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标签无关,问题是关于在两个导航状态之间保存滚动位置。

更多信息

选项卡组件,无论是react-tabs还是material-ui的tabs,都通过呈现所有选项卡并在选项卡之间移动时切换可见性来保持滚动位置。它将标签的样式设置为{height: 0, overflow: hidden},这样可以保持容器的滚动位置。

正如你提到的,当你改变根组件时,这不起作用,当组件重新加载时,滚动位置将重置。这可能是正确的行为,因为路由不能预先知道路由更改的副作用。

从这个相关的Github线程中引用Dan Abramov:

…这取决于您是否以同样的方式呈现您的组件。例如,如果你没有在本地缓存数据,路由器就无法恢复你的位置。但这也是浏览器的默认行为,我们只是试图模仿它

换句话说,根据这个范例,这不是路由器的责任,应该手动完成。