使用相交观察器渲染元素

时间:2019-06-12 08:59:45

标签: javascript

我尝试用交叉观察器实现无限滚动。我面临的问题是,当我到达倒数第二个位置时,api调用会触发并加载数据。

但是api调用发生了两次,我应该在这段代码中更新什么。

// app.js

import React, {Component} from 'react'
import Child from './child'
import axios from 'axios'

class App extends Component {
  state = {
    users: [],
    page: 0,
    loading: false,
    prevY: 0,
    isDataAvailable: false,
  }

  componentDidMount() {
    this.getUsers(this.state.page)
  }

  getUsers = (page = this.state.page) => {
    this.setState({loading: true})
    axios
      .get(`https://api.github.com/users?since=${page}&per_page=100`)
      .then(res => {
        console.log({users: res.data})
        this.setState({users: [...this.state.users, ...res.data]})
        this.setState({loading: false, isDataAvailable: true})
      })
  }

  handleObserver = (entities, observer) => {
    const y = entities[0].boundingClientRect.y
    if (this.state.prevY > y) {
      const lastUser = this.state.users[this.state.users.length - 1]
      const curPage = lastUser.id
      this.getUsers(curPage)
      this.setState({page: curPage})
    }
    this.setState({prevY: y})
  }

  render() {
    return (
      <div className="container">
        <div style={{minHeight: '800px'}}>
          {this.state.isDataAvailable ? (
            <Child
              handleObserver={this.handleObserver}
              users={this.state.users}
            />
          ) : null}
        </div>
      </div>
    )
  }
}

export default App

// child.js

import React, {Component} from 'react'

class Child extends Component {
  componentDidMount() {
    const options = {
      root: null,
      threshold: 0,
    }
    this.observer = new IntersectionObserver(
      this._handleObserver.bind(this),
      options,
    )
    this.observer.observe(this.loadingRef)
  }

  shouldComponentUpdate(nextProps) {
    return this.props.users !== nextProps.users
  }

  componentDidUpdate() {
    this.observer.observe(this.loadingRef)
  }

  _handleObserver(entities, observer) {
    console.log('called')
    this.props.handleObserver(entities)
  }

  render() {
    return (
      <ul>
        {this.props.users.map((user, index) =>
          index === this.props.users.length - 1 ? (
            <div>
              <div ref={loadingRef => (this.loadingRef = loadingRef)}>
                <b>
                  <h1>Target</h1>
                </b>
              </div>
              <li key={user.id}>{user.login}</li>
            </div>
          ) : (
            <li key={user.id}>{user.login}</li>
          ),
        )}
      </ul>
    )
  }
}

export default Child

任何帮助表示赞赏

请查看代码框和代码框控制台,您可以看到两次API调用发生时,到达目标时我仅需要调用一项服务。每个向下滚动100个结果。

https://codesandbox.io/s/react-codesandbox-nm8ik

0 个答案:

没有答案