Skip to content

10.getSnapshotBeforeUpdate应用案例

案例讲解请观看视频,这里呈现相关代码:

js

import React from './react';
import ReactDOM from './react-dom';
class ScrollingList extends React.Component {
  counter = 0
  isAppend = true
  intervalId = 0
  constructor(props) {
    super(props);
    this.listRef = React.createRef();
    this.state = {list: []}
  }
  // https://reactjs.org/docs/react-component.html#getsnapshotbeforeupdate
  // 1.该函数在render函数执行完成生成真实DOM后,DOM挂载到页面前执行
  // 2.该函数使得组件在DOM发生变化之前可以获取一些信息
  // 3.该函数返回的任何值都会作为componentDidUpdate的第三个参数传入
  // 4.该生命周期函数并不常用,仅仅在一些特定UI变化的场景才会用到
  getSnapshotBeforeUpdate(prevProps, prevState) {
    // Are we adding new items to the list?
    // Capture the scroll position so we can adjust scroll later.
    if (prevState.list.length < this.state.list.length) {
      const list = this.listRef.current;
      return list.scrollHeight - list.scrollTop;
    }
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    // If we have a snapshot value, we've just added new items.
    // Adjust scroll so these new items don't push the old ones out of view.
    // (snapshot here is the value returned from getSnapshotBeforeUpdate)
    if (snapshot !== null) {
      const list = this.listRef.current;
      list.scrollTop = list.scrollHeight - snapshot;
    }
  }

  appendData = () => {
    if(this.isAppend){
      this.intervalId = setInterval(()=>{
        this.setState({
          list: [...this.state.list, this.counter++]
        })
      },1000)
    }else{
      clearInterval(this.intervalId)
    }
    this.isAppend = !this.isAppend
  }

  render() {
    return (<div>
      <input type="button" onClick={()=>this.appendData()}  value={"追加/暂停追加数据"}/>
      <div  ref={this.listRef} style={{overflow: 'auto', height:'400px', background: '#efefef'}}>
        {
          this.state.list.map(item => {
            return <div key={item} style={{
              height: '60px',
              padding: '10px',
              marginTop: '10px',
              border: '1px solid blue',
              borderRadius: '6px'
            }}>{item}</div>
          })
        }
      </div>
      
      </div>
    );
  }
}
ReactDOM.render(<ScrollingList/>, document.getElementById('root'));

基于 VitePress 构建