RelayJS 无限滚动

Posted

技术标签:

【中文标题】RelayJS 无限滚动【英文标题】:RelayJS infinite scroll 【发布时间】:2017-01-25 12:43:32 【问题描述】:

我正在尝试在我的 React-Relay 前端进行无限滚动分页,但没有成功。

此刻,我有了这个 React 组件……

class List extends Component 
  state =  loading: false ;

  componentDidMount() 
    window.onscroll = () => 
      if (!this.state.loading
              && (window.innerHeight + window.scrollY)
              >= document.body.offsetHeight) 

        this.setState(loading: true, () => 
          this.props.relay.setVariables(
            count: this.props.relay.variables.count + 5
          , (readyState) => 
            if (readyState.done) 
              this.setState( loading: false );
            
          );
        );
      
    
  

  render() 
    return (
      <div>
        this.props.viewer.products.edges.map(function(product, i) 
          return (<Item key=i product=product.node />);
        )
      </div>
    );
  
;

...包裹在中继容器中

export default Relay.createContainer(List, 
  initialVariables: 
    count: 5
  ,
  fragments: 
    viewer: () => Relay.QL`
      fragment on Viewer 
        products(first: $count) 
          total
          edges 
            node 
              $Item.getFragment('product')
            
          
        
      
    `,
  
);

这背后的逻辑似乎很简单。如果您到达某个 scrollY 位置,请将新的增量值设置为 count 变量,这会扩展您的边列表。

但是这个概念会导致一种情况,一开始我在数据库中查询前 5 条记录,但最近我不断滚动查询 N+5 条记录。最后我会在数据库中查询整个表(数千条记录)!这是非常不可接受的。

所以我正在尝试实现cursors,但我不知道如何从连接中获取数据并扩展结果。这种方法返回给我一个 “分页” 列表。


另外,当我向下滚动时,上面的代码给了我这个错误

resolveImmediate.js?39d8:27 Uncaught Invariant Violation: performUpdateIfNecessary: Unexpected batch number (current 19, pending 18)

我将非常感谢任何帮助或示例!

【问题讨论】:

【参考方案1】:

问题解决了!

关于我每次滚动一次又一次地获取 N+5 记录的问题,Relay 似乎非常智能,因为它通过查询 cursor 和管理自动“分页”我的连接我的连接中的after arg。

在我的后端 graphql-sequelize 的帮助下,它只是变成了这个查询

SELECT ... FROM product ORDER BY product.id ASC LIMIT 5 OFFSET 10

这实际上解决了我关于性能的第一个问题。 :)

所以我的Relay.QL 查询已经转译成这个

query ListPage_ViewerRelayQL($id_0:ID!) 
  node(id:$id_0) 
    ...F1
  

fragment F0 on Product 
  id,
  title,
  price

fragment F1 on Viewer 
  _products4tSFq4:products(after:"YXJyYXljb25uZWN0aW9uJDUkNA==",first:5) 
    edges 
      cursor,
      node 
        id,
        ...F0
      
    ,
    pageInfo 
      hasNextPage,
      hasPreviousPage
    
  ,
  id

当我在我的 GraphQL 后端运行这个查询时,它返回了空结果


  "data": 
    "node": null
  

然后我立即意识到问题出在哪里以及为什么我的 Relay 崩溃了。

问题在于重新获取查看器。我没有正确实现nodeDefinitions,当查看器ID点击idFetchertypeResolver时,它失败并返回null。之后在客户端,Relay 无法完成我连接的重新获取并崩溃了!

经过小修和后端修复,我的无限滚动就像一个魅力! :)

【讨论】:

不明白您是如何将 N+5 的问题转为正常的,而“正常”分页具有固定数量的数据,可以连接每一轮,这样效率更高。

以上是关于RelayJS 无限滚动的主要内容,如果未能解决你的问题,请参考以下文章

无限滚动加载最佳实践

无限滚动时防止滚动条跳跃

尝试使用 Swift 实现无限滚动时陷入无限循环

1.10 中的 DataTables 无限滚动

Laravel 5 分页 + 无限滚动 jQuery

ios中具有自动滚动功能的无限Textview