【问题标题】:React Router Push SilentlyReact Router 静默推送
【发布时间】:2017-02-18 10:40:47
【问题描述】:

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

如果用户在 Tab 1 中,则路由将为 /home。当他滑动到 Tab 2 时,路线将是/home/news。当他滑动到 Tab 3 时,路线变为/home/about 等等。

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

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

有什么想法吗?谢谢。

【问题讨论】:

  • 在某些情况下使用shouldComponentUpdate来阻止渲染怎么样?
  • @azuim 我相信重新渲染是必要的,因为内容完全改变了。也许监听滚动事件并将 scrollTop 值保存在某处。即使在具有适当 id 的 localStorage 中。

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


【解决方案1】:

一种方法是将路由设置为指向同一个组件,并使用路由参数来设置当前选择的选项卡。通过这种方式,您可以实现您所追求的“静默”行为:

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

...由您决定以相同的方式渲染组件。例如,如果您不在本地缓存数据,则路由器无法恢复您的位置。但这也是浏览器默认行为的工作原理,我们只是试图模仿它

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

【讨论】:

    猜你喜欢
    • 2019-06-10
    • 1970-01-01
    • 2018-12-05
    • 1970-01-01
    • 1970-01-01
    • 2015-05-09
    • 1970-01-01
    • 2018-02-17
    • 2015-04-26
    相关资源
    最近更新 更多