在React中,我应该如何将开始经过的时间传递给秒表组件并从该时间开始运行增量器?

问题描述 投票:0回答:1

我可以根据拉动的开始时间获得静态经过的秒数,但是我无法获得经过的秒数然后继续计数。我知道我可能不应该使用道具来更新孩子的状态,但即使没有,我也无法让它工作并尝试将其作为一种解决方法。任何帮助表示赞赏。

父看起来像这样:

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      elapsedSeconds: -1
    };
    this.changeElapsedSecondsParent = this.changeElapsedSecondsParent.bind(this);
  }
  changeElapsedSecondsParent(newElapsed) {
    this.setState({
      elapsedSeconds: newElapsed
    });
  }
  render() {
    const { elapsedSeconds } = this.state;

   return (
     <div>
      <Stopwatch 
         elapsedSeconds={elapsedSeconds} 
         changeElapsed={this.changeElapsedSecondsParent}
       />
    </div>
    );
  }
}

儿童秒表看起来像这样:

const formattedSeconds = (sec) =>
  ~~(sec / 60) +
    ':' +
  ('0' + sec % 60).slice(-2)


export class Stopwatch extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      secondsElapsed: -1,
      laps: [],
      lastClearedIncrementer: null
    };
    this.incrementer = null;
    this.handleStartClick = this.handleStartClick.bind(this);
    this.handleStopClick = this.handleStopClick.bind(this);
    this.handleResetClick = this.handleResetClick.bind(this);
    this.handleLapClick = this.handleLapClick.bind(this);
  }

  componentDidMount() {
    if(this.state.secondsElapsed < 0) {
      const getElapsedTime = async () => {
        try{
          const response =  await fetch(`api url`);
          if(response.ok){
            let jsonResponse = await response.json();
            /* start getting seconds elapsed since start */
            let currentServerTime = new Date(jsonResponse[0].currentTimeStamp).getTime() /1000;
            let currentD = Math.floor(new Date().getTime()/1000);
            let deltaDate = (currentServerTime-currentD);
            let raceStartTime = new Date(jsonResponse[0].startTime).getTime()/1000 - deltaDate;
            let secondsElapsedSinceStart = currentD - raceStartTime;
            /* end getting seconds elapsed since start */
            this.props.changeElapsed(secondsElapsedSinceStart);
          }
        }
        catch(error){
          console.log(error);
        }
      }
      getElapsedTime();
      let newElapsed = this.props.elapsedSeconds;
      this.incrementer = setInterval( () =>
      this.setState({
      secondsElapsed: newElapsed + 1
      })
      , 1000);
    } else {
      this.incrementer = setInterval( () =>
      this.setState({
      secondsElapsed: this.state.secondsElapsed + 1
      })
      , 1000);
    }
  }

  handleStartClick() {
    /* start post request */
    const pushTime = async () => {
      try {
        const response = await fetch('apiurl', {
          method: 'POST',
          body: JSON.stringify({"startTime": "'2018-08-26 16:57:09'"})
        })
        if(response.ok){
          const jsonResponse = await response.json();
          return jsonResponse;
        }
        throw new Error('Request failed!');
      } catch(error) {
        console.log(error);
      }
    }
    pushTime();
  }

  handleStopClick() {
    clearInterval(this.incrementer);
    this.setState({
      lastClearedIncrementer: this.incrementer
    });
  }

  handleResetClick() {
    clearInterval(this.incrementer);
    this.setState({
      secondsElapsed: 0,
      laps: []
    });
  }

  handleLapClick() {
    this.setState({
      laps: this.state.laps.concat([this.props.elapsedSeconds])
    })
  }

  render() {
    return (
      <div className="stopwatch">
        <h1 className="stopwatch-timer">{formattedSeconds(this.state.secondsElapsed)}</h1>

        {(this.props.elapsedSeconds === 0 ||
          this.incrementer === this.state.lastClearedIncrementer
          ? <Button className="start-btn" onClick={this.handleStartClick.bind(this)}>start</Button>
          : <Button className="stop-btn" onClick={this.handleStopClick.bind(this)}>stop</Button>
        )}

        {(this.props.elapsedSeconds !== 0 &&
          this.incrementer !== this.state.lastClearedIncrementer
          ? <Button onClick={this.handleLapClick.bind(this)}>lap</Button>
          : null
        )}


        {(this.props.elapsedSeconds !== 0 &&
          this.incrementer === this.state.lastClearedIncrementer
          ? <Button onClick={this.handleResetClick.bind(this)}>reset</Button>
          : null
        )}

        <ul className="stopwatch-laps">
          { this.state.laps.map((lap, i) =>
              <li className="stopwatch-lap"><strong>{i + 1}</strong>/ {formattedSeconds(lap)}</li>)
          }
        </ul>
      </div>
    );
  }
}

const Button = (props) =>
  <button type="button" {...props} className={"btn " + props.className } />;
javascript reactjs web-applications state react-props
1个回答
0
投票

我发现在构造函数中定义常量更容易,如:

this.deltaTime = null;

然后我创建了一个changeDeltaTime函数:

changeDeltaTime(newTime) {
    this.deltaTime = newTime
}

最后,我在componentDidUpdate()生命周期方法中的响应之后更新了promise内的deltaTime。

await this.changeDeltaTime(deltaDate);

在渲染中,我等待通过父母传递的道具解决的承诺

return !this.props.finishedGet ? <span>Waiting on fetch...</span> : (this.renderStopwatch(this.state.time))

这也涉及要创建的renderStopwatch函数,但它基本上只包含一旦promise解决后应该创建的内容。

© www.soinside.com 2019 - 2024. All rights reserved.