簡體   English   中英

React.JS:定時狀態更改序列

[英]React.JS: Sequence of timed state changes

我有一個簡單的Web應用程序,其中包含一個父組件和三個子組件。 孩子們只是div框,可以根據其活動的屬性將背景顏色從白色更改為紅色。 animateChild()函數可用於將特定的孩子變成紅色,然后在1秒后再次變成白色。

我的目標是“播放”任意子動畫序列,每個動畫之間的間隔為1s。 這應該在animateSequence()函數中發生。

實現此目的的最初想法是使用for循環,並在每次迭代時在window.setTimeout()中調用animateChild(childNum) 但是,這沒有用。 我猜是因為setState()是異步的,並且幾個狀態更改被合並在一起。

什么是完成動畫序列(例如,子1,子2,子3)的最佳方法,每個動畫之間的間隔時間為1s? 非常感謝你

JavaScript代碼:

class Child extends React.Component {

  render() {
    var childStyle = "basic"; 
    if (this.props.active){
      childStyle += " active";
    }
    return (
        <div className={childStyle}></div>
    );
  }
}


class Parent extends React.Component {
  constructor(){
    super();
    this.state = {
      firstChildActive:false,
      secondChildActive:false,
      thirdChildActive:false,
    };
    this.animateChild = this.animateChild.bind(this);

  }


  animateChild(childNum){
    var childDict = ["firstChildActive","secondChildActive","thirdChildActive"];
    this.setState({[childDict[childNum]]: true}, function() {

        window.setTimeout(() => {
        this.setState({[childDict[childNum]]: false});

        },1000);
    });
  }

  animateSequence(){
    // animate child 2, then child 1, then child 3, then child 1, etc.
  }

  render() {
    return (
      <div className ="container">
      <Child active={this.state.firstChildActive}/>
      <Child active={this.state.secondChildActive}/>
      <Child active={this.state.thirdChildActive}/>
      </div>
    );
  }
}


ReactDOM.render(<Parent />,document.getElementById('app'));

CSS代碼:

.container{
  display:flex;
  width:100%;
  justify-content: space-between;

}

.basic{
  margin: 10px;
  width: 100px;
  height:100px;
  border: 2px solid black;
}

.active{
  background: red;
}

Codepen: https ://codepen.io/miga89/full/owgZea/

我也將您的子組件轉換為無狀態組件,解決方案只是使用一個簡單的setInterval。

https://codepen.io/anon/pen/LLEyVo

const Child = ({ isActive }) => {
    var childStyle = "basic"; 
    if ( isActive ) childStyle += " active";
    return <div className={ childStyle }></div>
}

class Parent extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      firstChildActive  : false,
      secondChildActive : false,
      thirdChildActive  : false,
    };
  }

  animateSequence(){

    const TOTAL = 3;
    const CHILD_DICT = ["firstChildActive","secondChildActive","thirdChildActive"];

    let run = 0;

    var setActive = setInterval( () => {
      this.setState({ [CHILD_DICT[run]]: true });
      run = run + 1;
      if( run === TOTAL ) {
        clearInterval(setActive);
      }
    }, 1000)

  }

  render() {
    return (
      <div className ="container">
        <button onClick={ () => this.animateSequence() }>Run Sequence</button>
      <Child isActive={this.state.firstChildActive }/>
      <Child isActive={this.state.secondChildActive } />
      <Child isActive={this.state.thirdChildActive }/>
      </div>
    );
  }
}


ReactDOM.render(<Parent />,document.getElementById('app'));

您的此上下文在第一個setState的回調中無效。

var childDict = ["firstChildActive","secondChildActive","thirdChildActive"];
this.setState({[childDict[childNum]]: true}, function() {

應該

var childDict = ["firstChildActive","secondChildActive","thirdChildActive"];
this.setState({[childDict[childNum]]: true}, () => {

如果要在不使用按鈕的情況下執行此操作,請在原型中使用componentDidMount方法:

 componentDidMount(){
  this.animateSequence();
}
  render() {
    return (
      <div className ="container">        
      <Child isActive={this.state.firstChildActive }/>
      <Child isActive={this.state.secondChildActive } />
      <Child isActive={this.state.thirdChildActive }/>
      </div>
    );
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM