反应路由器静默推送

时间:2016-10-10 03:40:06

标签: javascript reactjs redux react-router react-router-redux

就我而言,我有几个标签。标签容器可以刷卡。如果用户切换选项卡,路由也将更新。 例如:

如果用户位于标签1中,则路线为/home。当他滑动到选项卡2时,路线将为/home/news。当他滑动到Tab 3时,路线变为/home/about依此类推。

我知道可以使用this.props.push(NEXTROUTE)来实现。但通过这样做,组件被重新渲染并使我失去上一个选项卡的最后滚动位置。我的情况需要保留标签的最后滚动位置,而不是滚动到顶部。

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

有什么想法?感谢。

1 个答案:

答案 0 :(得分:1)

一种方法是将路径设置为指向同一个Component,并使用route params设置当前选择的选项卡。通过这种方式,您可以实现目标的“无声”行为:

<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:

  

...由您自己以相同的方式呈现组件。例如,如果您不在本地缓存数据,那么路由器无法恢复您的位置。但这也是浏览器默认行为的作用,我们只是试图模仿它

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

相关问题