繁体   English   中英

为什么React无法正确更新dom?

[英]Why doesn't React update dom properly?

我有这个ReactJS类:

import React from 'react';

export default class Test extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      status: 'main',
    };
  }

  applyTransition() {
    this.setState({
      status: 'leaving',
    }, () => {
      setTimeout(() => {
        this.setState({
          status: 'entering'
        }, () => setTimeout(() => {
          this.setState({
            status: 'main',
          });
        }, 1000));
      }, 1)
    });
  }
  handleClick() {
    this.applyTransition();
  }
  computeStyle() {
    switch (this.state.status) {
      case 'leaving':
        return {
          transform: 'translate(-100%)',
        };
      case 'entering':
        return {
          transform: 'translate(0%)',
          transition: 'transform 1s',
        };
      case 'main':
        return {
          transform: 'translate(0%)',
        };
    }
  }

  render() {
    const style = this.computeStyle();
    return (
      <div>
        <div style={_.merge({}, style, {
            display: 'flex',
            flexOrientation: 'row',
          })}>
          <div>1</div>
          <div>2</div>
          <div>3</div>
        </div>
        <button onClick={() => this.handleClick()}>Click</button>
      </div>
    );
  }
}

我的工作流程如下,我处于正常显示内容的“主要”状态,我希望将内容向左翻译的“之前转换”状态,以及我希望将内容转换为“过渡”状态的状态内容通过CSS转换恢复原状。

如果我不使用1 ms的超时,似乎react无法正确更新DOM。 因此,过渡不起作用。 为什么?

编辑:

那么,如何确保CSS转换工作流程完成? 我希望在state.status变量的每次更改时都可以正确更新和呈现DOM。

我不想使用ReactCSSTransitionGroup,因为我想了解如何从头开始创建一些自定义CSS过渡。

即使我对浏览器中的渲染队列的工作方式不是很熟悉,但我还是假定您不能在没有延迟的情况下分配相反的CSS属性。 就像向左过渡-然后再次向右过渡。

它可能与React本身无关。

看这里: https : //jsbin.com/geqogeqifa/edit?html,输出

编辑:(大量猜测)
由于渲染输出和JS在浏览器中使用相同的事件队列,因此在“离开”和“输入” css属性分配之间不会发生任何重新渲染–这导致最后一个属性甚至在第一个属性被渲染之前都覆盖了第一个属性。 。

所以我的猜测是,通过使用超时,您可以在事件队列中插入另一个事件,该事件在先前的渲染事件发生后被调用…

伪事件队列:

没有超时:

Event(JS): css(leaving), css(entering)
Event(Render) // renders only entering

随着超时:

Event(JS): css(leaving), setTimeOut(css(entering))
Event(Render) // renders leaving
Event(timeOut): css(entering)
Event(Render) // renders entering

如果您只是尝试对现有元素进行动画处理(这似乎是基于您的代码的情况),那么这将是一种简单得多的方法:

constructor() {
  super();
  this.state = {enter: false};
}

handleClick() {
  this.setState({
    enter: true
  });
}

computeStyle(enter) {
  return {
    transform: enter ? 'translate(0%)' : 'translate(-100%)',
    transition: 'transform 1s'
  };
}

render() {
  const style = this.computerStyle(this.state.enter);

  // divs and stuff with your style

  <button onClick={this.handleClick} />
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM