Skip to content

Latest commit

 

History

History
69 lines (56 loc) · 1.91 KB

discussion.md

File metadata and controls

69 lines (56 loc) · 1.91 KB

Timer

I was really looking forward to this as working with async events is quite natural in JS.

class Timer extends React.PureComponent {
  state = {
    duration: 20,
    value: 0
  };
  componentDidMount = () => (this.interval = setInterval(this.tick, 100));

  componentWillUnmount = () => clearInterval(this.interval);

  // render method omitted

  handleDurationChange = e => {
    this.setState({ duration: Number(e.target.value) });
  };

  reset = () => this.setState({ value: 0 });

  tick = () => {
    this.setState(state => ({
      value: state.value >= state.duration ? state.value : round(state.value + 0.1, 1)
    }));
  };
}

As you can see, we only need 2 states for this UI: The total duration and the current value. On mount we start an interval to increase the current value, if it is lower than the max duration (see the tick method).

User interactions (rest button and change of the slider) are simply merged into the state of the component, the tick method automatically uses the current values from state to update correctly.

// ...

render = () => (
  <Wrapper>
    <Element>
      <Label>Elapsed Time</Label>
      <Value>
        <ProgressBar value={this.state.value / this.state.duration} />
      </Value>
    </Element>
    <Element>
      <Label>Elapsed seconds</Label>
      <Value>{this.state.value.toFixed(1)}s</Value>
    </Element>
    <Element>
      <Label>Duration</Label>
      <Value>
        <Input
          type="range"
          onChange={this.handleDurationChange}
          min={0}
          max={60}
          value={this.state.duration}
        />
      </Value>
    </Element>
    <Button onClick={this.reset}>Reset</Button>
  </Wrapper>
);

//...

The render methods is just displaying the current state. In React, when writing the render method, you can assume that there are no async effects. The state is just there and you describe how your UI should look like.