Reactjs 如何在componentDidMount后运行setInterval,并在道具更新后重新运行它?

Reactjs 如何在componentDidMount后运行setInterval,并在道具更新后重新运行它?,reactjs,Reactjs,这是我的代码笔代码 let jsonData = { value: [1,2,3,4,5,6,7,8,9,10] } class Father extends React.Component { constructor(props) { super(props); this.state = { data: jsonData,//data from websocket } } render() { const arr = this.st

这是我的代码笔代码

let jsonData = {
  value: [1,2,3,4,5,6,7,8,9,10]
}

class Father extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: jsonData,//data from websocket
    }
  }
  render() {
    const arr = this.state.data.value;
    return (
      <Child arr={arr} />
    );
  }
}

class Child extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      style: null,
      arr: this.props.arr
    };
  }

  getNodePositionBottom(ref) {
    const nodeY = ReactDOM.findDOMNode(ref).getBoundingClientRect().bottom;
    return nodeY;
  }

  getNodePositionTop(ref) {
    const nodeY = ReactDOM.findDOMNode(ref).getBoundingClientRect().top;
    return nodeY;
  }

  componentDidMount() {
    const divBottom = this.getNodePositionBottom(this.div);
    const divTop = this.getNodePositionTop(this.div);
    const height = divBottom - divTop;

    const ulBottom = this.getNodePositionBottom(this.ul);
    const ulTop = this.getNodePositionTop(this.ul);
    const heightUL = ulBottom - ulTop;

    if (ulBottom > divBottom) {
      this.scrollingTop = setInterval(
        function(){
          this.offsetY = this.offsetY || 0;
          if (ulBottom > divTop && this.offsetY + heightUL!== 0) {
            this.offsetY -= 1;
            this.setState({
              style: {top: + this.offsetY + "px"}
            });
          } else {
            this.setState({
              style: {top: height + "px"}
            });
            this.offsetY = height;
          }
        }.bind(this),
        20
      );
    }
  }

  render() {
    const arr = this.state.arr;
    let arrList = arr.map((name, i) => <li key={i} className="list">{name}</li>);
    return (
      <div ref={(div) => {this.div = div}} className="father">
        <ul ref={(ul) => {this.ul = ul}} className="child" style={this.state.style}>
          {arrList}
        </ul>
      </div>
    );
  }
}

ReactDOM.render(<Father />, document.getElementById("app"));
让jsonData={
值:[1,2,3,4,5,6,7,8,9,10]
}
类父类扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
数据:jsonData,//来自websocket的数据
}
}
render(){
const arr=this.state.data.value;
返回(
);
}
}
子类扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
样式:空,
这个。道具。啊
};
}
getNodePositionBottom(参考){
const nodeY=ReactDOM.findDOMNode(ref.getBoundingClientRect().bottom;
返回诺迪;
}
getNodePositionTop(参考){
const nodeY=ReactDOM.findDOMNode(ref.getBoundingClientRect().top;
返回诺迪;
}
componentDidMount(){
const divBottom=this.getNodePositionBottom(this.div);
const divTop=this.getNodePositionTop(this.div);
const height=divBottom-divTop;
const ulBottom=this.getNodePositionBottom(this.ul);
const ulTop=this.getNodePositionTop(this.ul);
常数heightUL=ulBottom-ulTop;
if(ulBottom>divBottom){
this.scrollingTop=setInterval(
函数(){
this.offsetY=this.offsetY | | 0;
如果(ulBottom>divTop&&this.offsetY+heightUL!==0){
此.offsetY-=1;
这是我的国家({
样式:{top:+this.offsetY+“px”}
});
}否则{
这是我的国家({
样式:{top:height+“px”}
});
this.offsetY=高度;
}
}.绑定(此),
20
);
}
}
render(){
const arr=this.state.arr;
设arrList=arr.map((name,i)=>
  • {name}
  • ); 返回( {this.div=div}}className=“父亲”>
      {this.ul=ul}}className=“child”style={this.state.style}> {arrList}
    ); } } ReactDOM.render(,document.getElementById(“app”);
    我试图构建一个列表,如果列表高度高于容器,则在渲染后自动滚动到上面。通过websocket数据更新列表成员,在每个websocket消息之后,更新列表成员,并再次比较高度以确定是否自动滚动

    我对React是新手,所以我想到的就是设置一个“样式”状态,计算组件中的偏移量,然后重新设置状态,所以React将再次渲染

    在我发现两个问题之前,它运行良好

    第一个问题是我想通过websocket数据更新这个列表,我认为“道具改变了,它会重新呈现,因此状态也改变了”,但这会搞乱第二个问题,似乎我把这个自动滚动部分弄错了

    正如您所知,组件通常通过每个状态渲染一次,但在这种情况下,我可能会将状态设置太多次,每20毫秒一次,我担心性能

    每次从websocket服务器推送后,列表确实会变为新列表,但它会停止自动滚动

    总而言之:

    1“每隔20毫秒设置一次状态以执行自动滚动”是否错误

    2为什么在通过道具更新后停止自动滚动?我应该使用componentDidUpdate吗?但这种生命周期方法会弄乱自动滚动,因为它会频繁运行

  • 我不确定每20毫秒自动滚动是好是坏,但在我看来,滚动应该只发生在更多的项目被添加到您的列表。不确定触发web套接字获取的频率(我不太熟悉web套接字)

  • 我猜你想在道具改变时自动滚动。为此,理想的组件事件是
    ComponentWillReceiveProps
    ,它具有nextrops(新的props本身)。你可以比较当前的道具和下一个道具,看看是否有任何变化,如果有,然后启动滚动

  • 例如:

    ComponentWillReceiveProps(nextProps){
      if (this.props.myName !== nextProps.myName) {
        // do the code
      }
    }
    

    我用ComponentWillReceiveProps解决了这个问题,除了生命周期方法之外,我还需要在setInterval中重置一些变量,这样它就可以计算出正确的偏移量。多亏了你们,现在我对生命周期有了更多的了解。