Lifting State Up in React With StopWatch Example

Lifting State Up in React With StopWatch Example

Many times there is a need of sharing the same data with multiple components in react js to achieve this react provides a very beautiful concept called Lifting Up state. According to react.org whenever there is a need of sharing the same changing data with multiple components then that time we should share the state to a closest common ancestor.

I know above sentence does not make much sense Let’s understand this using the example of a stopwatch.

Creating STOPWATCH using react js

Here in this stopwatch example will be divided into two sections.

  1. In first section we will create a simple stop watch using single component.
  2. In this second second section we will divide our component created in first section into multiple component and will share shared data to these component using the concept of state lifting.

Section 1: Creating Stopwatch app in react js using single component

Let’s see what we will create. We will create a stopwatch app using react. which will have functionality like

start: that will start the stop watch.

pause: Will pause the stop watch a given moment.

Stop: Will stop the stop the stopwatch.

Below gif shows how our stopwatch will look like.

stopwatch | techijournal.com
STOPWATCH app in react with STOP, START and PAUSE functionality

Let’s create a react project call stopwatch. If don’t know how to create react app then we have post here to help you create react app. When you are done generating your stopwatch react app. Then we will create one component folder under src which will hold all the components for stopwatch.

Let’s create a stopwatchcomponent.jsx under src->component folder.

Adding various statuses for stopwatchcomponent.jsx which will act as constant

stopWatchStatuses = {
    PAUSED: "paused",
    STOPED: "stoped",
    RUNNING: "running",
  };

whenever our component is loaded we will initially have stopwatch status as STOPPED. This we be assigned to our variable

  stopWatchStatus = this.stopWatchStatuses.STOPED;

Now we will add constructor to our component which we declare state with variables like

  1. hrs : will denote hour element of stopwatch
  2. min: min denote minute element of stopwatch.
  3. sec: This will denote second element of stopwatch.
  4. mils: mils will denote milisecond of stop watch.
  5. pauseDisabled: pauseDisabled will denote that pause button will be disabled or not.
constructor(props) {
    super(props);
    this.state = {
      hrs: "00",
      min: "00",
      sec: "00",
      mils: "000",
      pauseDisabled: true,
    };
  }

Now we will have our render() that will return view for our stop watch.

render() {
    const heightWeidth = {
      fontSize: "xx-large",
    };
    return (
      <React.Fragment>
        <div class="card text-center border-success m-3">
          <div class="card-body">
            <div>
              <div className="badge badge-success mr-2">
                <span className="text-monospace" style={heightWeidth}>
                  {this.state.hrs}
                </span>
              </div>

              <div className="badge badge-success mr-2">
                <span className="text-monospace" style={heightWeidth}>
                  {this.state.min}
                </span>
              </div>

              <div className="badge badge-success mr-2">
                <span className="text-monospace" style={heightWeidth}>
                  {this.state.sec}
                </span>
              </div>

              <div className="badge badge-success ">
                <span className="text-monospace" style={heightWeidth}>
                  {this.state.mils}
                </span>
              </div>
            </div>
          </div>
          <div class="card-footer bg-warning p-0">
            {" "}
            <div>
              <button
                className="btn btn-sm btn-success m-2"
                onClick={this.stopWatchBtnEvent("start")}
              >
                <span className={this.stopWatchBtnCss("start")}></span>
              </button>

              <button
                className="btn btn-sm btn-success"
                onClick={this.stopWatchBtnEvent("pause")}
                disabled={this.state.pauseDisabled}
              >
                <span className={this.stopWatchBtnCss("pause")}></span>
              </button>
            </div>
          </div>
        </div>
      </React.Fragment>
    );
  }

Here we can see that we have used bootstrap css element to style our view. If you want to know about adding bootstrap to react js you can follow this post.

Note, above we have two buttons of start and pause type. which will be used to stop-start or pause the stopwatch. Just make sure to remember this types as we will be using these terms frequently as we proceed further.

Making it more clear, start button will have two functionality it will start the stop watch or stop. depending on stopwatchstatus. start type of the button will be used to assign css. And simillary stop type button will have two functionality to pause stopwatch or resume the stopwatch. that depend on stopwatchstatus.

stopWatchBtnCss(btnType) {
    console.log("stopWatchBtnCss called");
    if (btnType === "start") {
      if (this.stopWatchStatus === this.stopWatchStatuses.STOPED) {
        return "fa fa-play";
      }
      if (
        this.stopWatchStatus === this.stopWatchStatuses.RUNNING ||
        this.stopWatchStatus === this.stopWatchStatuses.PAUSED
      ) {
        return "fa fa-stop";
      }
    }
    if (btnType === "pause") {
      if (this.stopWatchStatus === this.stopWatchStatuses.STOPED) {
        return "fa fa-pause disabled";
      }
      if (this.stopWatchStatus === this.stopWatchStatuses.RUNNING) {
        return "fa fa-pause";
      }
      if (this.stopWatchStatus === this.stopWatchStatuses.PAUSED) {
        return "fa fa-play";
      }
    }
  }

stopWatchBtnCss() will decide the css of the button clicked on basis of its type and stopWatchStatus. i.e

For button, of type start, whenever the stopWatchStatus is STOPPED then this button will show play icon and when stopWatchStatus is RUNNING or PAUSED then button will show stop icon.

For button, of type pause, whenever the stopWatchStatus is RUNNING then this button will show pause icon and when stopWatchStatus is PAUSED then the button will show play icon.

 stopWatchBtnEvent(btnType) {
    console.log("stopWatchBtnEvent called");
    if (btnType === "start") {
      if (this.stopWatchStatus === this.stopWatchStatuses.STOPED) {
        return this.startStopWatch;
      }
      if (
        this.stopWatchStatus === this.stopWatchStatuses.RUNNING ||
        this.stopWatchStatus === this.stopWatchStatuses.PAUSED
      ) {
        return this.stopStopWatch;
      }
    }
    if (btnType === "pause") {
      if (this.stopWatchStatus === this.stopWatchStatuses.STOPED) {
        return this.pauseStopWatch;
      }
      if (this.stopWatchStatus === this.stopWatchStatuses.RUNNING) {
        return this.pauseStopWatch;
      }
      if (this.stopWatchStatus === this.stopWatchStatuses.PAUSED) {
        return this.startStopWatch;
      }
    }
  }

stopWatchBtnEvent(btntype) will decide which action to be performed on the click of button on the basis of its type and stopWatchStatus. i.e

For button, of type start, whenever the stopWatchStatus is STOPPED then whenever this button of type start is clicked then it will start the stopwatch by calling startstopWatch(). And when stopWatchStatus is RUNNING or PAUSED then it will call stopStopWatch()

For button, of type start, whenever the stopWatchStatus is RUNNING then whenever this button of type pause is clicked then it will pause the stopwatch by calling pauseStopWatch(). And when stopWatchStatus isPAUSED then it will call startStopWatch()

Now, we will create a functionality that will start the stopwatch.

startStopWatch = () => {
    console.log("Stop watch started.");
    if (this.interval == null) {
      this.interval = setInterval(this.updateTimes, 10);
    }
    this.stopWatchStatus = this.stopWatchStatuses.RUNNING;
  };
  updateTimes = () => {
    let date = new Date();
    let mils = parseInt(this.state.mils);
    let hrs = parseInt(this.state.hrs);
    let min = parseInt(this.state.min);
    let sec = parseInt(this.state.sec);
    mils = mils + 10;
    if (mils === 1000) {
      mils = 0;
      sec = sec + 1;
    }
    if (sec === 60) {
      sec = 0;
      min = min + 1;
    }
    if (min === 60) {
      min = 0;
      hrs = hrs + 1;
    }
    if (hrs === 24) {
      clearInterval(this.interval);
    }
    hrs = String(hrs).padStart(2, "0");
    min = String(min).padStart(2, "0");
    sec = String(sec).padStart(2, "0");
    mils = String(mils).padStart(3, "0");

    this.setState({
      hrs: hrs,
      min: min,
      sec: sec,
      mils: mils,
      pauseDisabled: false,
    });
  };

startStopWatch() the method will take care of two functionality first it will call updateTimes() at an interval of 10 millisecond. and sencondly will update the stopWatchStatus to RUNNING.

 stopStopWatch = () => {
    console.log("Stop watch stopped");
    clearInterval(this.interval);
    this.interval = null;
    this.setState({
      hrs: "00",
      min: "00",
      sec: "00",
      mils: "000",
      pauseDisabled: true,
    });
    this.stopWatchStatus = this.stopWatchStatuses.STOPED;
  };

stopStopWatch() method will stop the stop watch whenever called, stopStopWatch() will update the stopWatchStatus to STOPPED. and will update the state time element to zero and disable the pause button.

 pauseStopWatch = () => {
    console.log("Stop watch paused");
    clearInterval(this.interval);
    this.interval = null;
    this.stopWatchStatus = this.stopWatchStatuses.PAUSED;
    this.setState({
      hrs: this.state.hrs,
      min: this.state.min,
      sec: this.state.sec,
      mils: this.state.mils,
    });
  };

pauseStopWatch() will pause the stopwatch whenever called and will update the stopWatchStatus to PAUSED. pauseStopWatch() method will also update the state’s current state value.

We are done with our section 1. Here we created stopwatch using single component. Let’s check the complete code below

stopwatchcomponent.jsx

import React, { Component } from "react";
import "bootstrap/dist/css/bootstrap.css";
import "font-awesome/css/font-awesome.min.css";

class StopWatch extends Component {
  interval = null;
  stopWatchStatuses = {
    PAUSED: "paused",
    STOPED: "stoped",
    RUNNING: "running",
  };
  stopWatchStatus = this.stopWatchStatuses.STOPED;
  constructor(props) {
    super(props);
    this.state = {
      hrs: "00",
      min: "00",
      sec: "00",
      mils: "000",
      pauseDisabled: true,
    };
  }
  render() {
    const heightWeidth = {
      fontSize: "xx-large",
    };
    return (
      <React.Fragment>
        <div class="card text-center border-success m-3">
          <div class="card-body">
            <div>
              <div className="badge badge-success mr-2">
                <span className="text-monospace" style={heightWeidth}>
                  {this.state.hrs}
                </span>
              </div>

              <div className="badge badge-success mr-2">
                <span className="text-monospace" style={heightWeidth}>
                  {this.state.min}
                </span>
              </div>

              <div className="badge badge-success mr-2">
                <span className="text-monospace" style={heightWeidth}>
                  {this.state.sec}
                </span>
              </div>

              <div className="badge badge-success ">
                <span className="text-monospace" style={heightWeidth}>
                  {this.state.mils}
                </span>
              </div>
            </div>
          </div>
          <div class="card-footer bg-warning p-0">
            {" "}
            <div>
              <button
                className="btn btn-sm btn-success m-2"
                onClick={this.stopWatchBtnEvent("start")}
              >
                <span className={this.stopWatchBtnCss("start")}></span>
              </button>

              <button
                className="btn btn-sm btn-success"
                onClick={this.stopWatchBtnEvent("pause")}
                disabled={this.state.pauseDisabled}
              >
                <span className={this.stopWatchBtnCss("pause")}></span>
              </button>
            </div>
          </div>
        </div>
      </React.Fragment>
    );
  }
  startStopWatch = () => {
    console.log("Stop watch started.");
    if (this.interval == null) {
      this.interval = setInterval(this.updateTimes, 10);
    }
    this.stopWatchStatus = this.stopWatchStatuses.RUNNING;
  };
  updateTimes = () => {
    let date = new Date();
    let mils = parseInt(this.state.mils);
    let hrs = parseInt(this.state.hrs);
    let min = parseInt(this.state.min);
    let sec = parseInt(this.state.sec);
    mils = mils + 10;
    if (mils === 1000) {
      mils = 0;
      sec = sec + 1;
    }
    if (sec === 60) {
      sec = 0;
      min = min + 1;
    }
    if (min === 60) {
      min = 0;
      hrs = hrs + 1;
    }
    if (hrs === 24) {
      clearInterval(this.interval);
    }
    hrs = String(hrs).padStart(2, "0");
    min = String(min).padStart(2, "0");
    sec = String(sec).padStart(2, "0");
    mils = String(mils).padStart(3, "0");

    this.setState({
      hrs: hrs,
      min: min,
      sec: sec,
      mils: mils,
      pauseDisabled: false,
    });
  };

  stopStopWatch = () => {
    console.log("Stop watch stopped");
    clearInterval(this.interval);
    this.interval = null;
    this.setState({
      hrs: "00",
      min: "00",
      sec: "00",
      mils: "000",
      pauseDisabled: true,
    });
    this.stopWatchStatus = this.stopWatchStatuses.STOPED;
  };

  pauseStopWatch = () => {
    console.log("Stop watch paused");
    clearInterval(this.interval);
    this.interval = null;
    this.stopWatchStatus = this.stopWatchStatuses.PAUSED;
    this.setState({
      hrs: this.state.hrs,
      min: this.state.min,
      sec: this.state.sec,
      mils: this.state.mils,
    });
  };
  stopWatchBtnCss(btnType) {
    console.log("stopWatchBtnCss called");
    if (btnType === "start") {
      if (this.stopWatchStatus === this.stopWatchStatuses.STOPED) {
        return "fa fa-play";
      }
      if (
        this.stopWatchStatus === this.stopWatchStatuses.RUNNING ||
        this.stopWatchStatus === this.stopWatchStatuses.PAUSED
      ) {
        return "fa fa-stop";
      }
    }
    if (btnType === "pause") {
      if (this.stopWatchStatus === this.stopWatchStatuses.STOPED) {
        return "fa fa-pause disabled";
      }
      if (this.stopWatchStatus === this.stopWatchStatuses.RUNNING) {
        return "fa fa-pause";
      }
      if (this.stopWatchStatus === this.stopWatchStatuses.PAUSED) {
        return "fa fa-play";
      }
    }
  }
  stopWatchBtnEvent(btnType) {
    console.log("stopWatchBtnEvent called");
    if (btnType === "start") {
      if (this.stopWatchStatus === this.stopWatchStatuses.STOPED) {
        return this.startStopWatch;
      }
      if (
        this.stopWatchStatus === this.stopWatchStatuses.RUNNING ||
        this.stopWatchStatus === this.stopWatchStatuses.PAUSED
      ) {
        return this.stopStopWatch;
      }
    }
    if (btnType === "pause") {
      if (this.stopWatchStatus === this.stopWatchStatuses.STOPED) {
        return this.pauseStopWatch;
      }
      if (this.stopWatchStatus === this.stopWatchStatuses.RUNNING) {
        return this.pauseStopWatch;
      }
      if (this.stopWatchStatus === this.stopWatchStatuses.PAUSED) {
        return this.startStopWatch;
      }
    }
  }
}

export default StopWatch;

Even you can get code till this section on github.

Section 2: Splitting our component into multiple components and Lifting up the shared state.

In Section 1 of the post we created a Stopwatch using single component in react js. Some thing like this

Stowatch Component architecture

But now we want to divide this component into several small independent component. And also we want one extra component that will hold information for laps.

New architecture of our component will be something like this.

Stopwatch divided into multiple component.
Stopwatch divided into multiple component.

Here

Now in the above image you can clearly see that our stopwatch component is divided into several small components. Let’s discuss each of them.

Component NameDiscription
StopWatch ComponentThis component is the ancestor component and will share its common state values to other child component.
StopWatchView ComponentStopwathView component will display timer html view.
StopwatchControls ComponentStopwatchControlls will hold all button controls like STOP, PAUSE and Lapse button.
StopWatchLaps ComponentThis will show list of Laps

Here what we did is, as our view component and laps component will require hrs, min, sec and mils to display timer value or laps value. And this both component should be sink with the stopwatch actual value. Thats why we would not maintain individual state for these components instead we will lift up its state to nearest ancestor that will be our StopWatchComponent. And state of StopWatch component will be shared to other laps and stopwatchview component. This is called Lifting State up in react.

Lets check code.

Ancestor Component Stopwatch.jsx

import React, { Component } from "react";
import logo from "./logo.svg";
import "./App.css";
import StopWatchView from "./component/StopWatchView";
import StopWatchControl from "./component/stopwatchcontrolls";
import StopWatchLapsView from "./component/StopWatchLapsView";

class StopWatch extends Component {
  stopWatchStatuses = {
    PAUSED: "paused",
    STOPED: "stoped",
    RUNNING: "running",
  };
  constructor(props) {
    super(props);
    this.state = {
      hrs: "00",
      min: "00",
      sec: "00",
      mils: "000",
      pauseDisabled: true,
      lapsDisabled: true,
      stopWatchStatus: this.stopWatchStatuses.STOPED,
      laps: new Array(),
    };
  }
  style = {
    maxWidth: "40rem",
    padding: "100px 0",
  };

  render() {
    return (
      <div className="App">
        <div className="row">
          <div className="col col-sm-12 mx-auto" style={this.style}>
            <div className="row">
              <div className="col col-sm-7">
                <div className="card mb-3 border-success">
                  <div className="card-body">
                    <h5 className="">STOP WATCH </h5>

                    <StopWatchView
                      hrs={this.state.hrs}
                      min={this.state.min}
                      sec={this.state.sec}
                      mils={this.state.mils}
                    />
                  </div>
                  <div className="card-footer  bg-warning">
                    <StopWatchControl
                      pauseDisabled={this.state.pauseDisabled}
                      onstartStopWatch={this.startStopWatch}
                      onPauseStopWatch={this.pauseStopWatch}
                      onStopStopWatch={this.stopStopWatch}
                      stopWatchStatus={this.state.stopWatchStatus}
                      lapsDisabled={this.state.lapsDisabled}
                      onLapsClick={this.lapsClick}
                    />
                  </div>
                </div>
              </div>
              <div className="col col-sm-5">
                <h5 className="">LAPS </h5>

                <StopWatchLapsView laps={this.state.laps} />
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  }
  startStopWatch = () => {
    console.log("Stop watch started.");
    if (this.interval == null) {
      this.interval = setInterval(this.updateTimes, 10);
    }
    console.log("Setting Stop watch state as.", this.stopWatchStatuses.RUNNING);

    this.setState({
      stopWatchStatus: this.stopWatchStatuses.RUNNING,
      lapsDisabled: false,
    });
  };
  updateTimes = () => {
    let date = new Date();
    let mils = parseInt(this.state.mils);
    let hrs = parseInt(this.state.hrs);
    let min = parseInt(this.state.min);
    let sec = parseInt(this.state.sec);
    mils = mils + 10;
    if (mils === 1000) {
      mils = 0;
      sec = sec + 1;
    }
    if (sec === 60) {
      sec = 0;
      min = min + 1;
    }
    if (min === 60) {
      min = 0;
      hrs = hrs + 1;
    }
    if (hrs === 24) {
      clearInterval(this.interval);
    }
    hrs = String(hrs).padStart(2, "0");
    min = String(min).padStart(2, "0");
    sec = String(sec).padStart(2, "0");
    mils = String(mils).padStart(3, "0");

    this.setState({
      hrs: hrs,
      min: min,
      sec: sec,
      mils: mils,
      pauseDisabled: false,
    });
  };

  pauseStopWatch = () => {
    console.log("Stop watch paused", this.state.stopWatchStatus);
    clearInterval(this.interval);
    this.interval = null;
    this.setState({
      hrs: this.state.hrs,
      min: this.state.min,
      sec: this.state.sec,
      mils: this.state.mils,
      stopWatchStatus: this.stopWatchStatuses.PAUSED,
      lapsDisabled: true,
    });
  };

  stopStopWatch = () => {
    console.log("Stop watch stopped");
    clearInterval(this.interval);
    this.interval = null;
    this.setState({
      hrs: "00",
      min: "00",
      sec: "00",
      mils: "000",
      pauseDisabled: true,
      stopWatchStatus: this.stopWatchStatuses.STOPED,
      lapsDisabled: true,
      laps: new Array(),
    });
  };
  lapsClick = () => {
    const value =
      this.state.hrs +
      ":" +
      this.state.min +
      ":" +
      this.state.sec +
      "." +
      this.state.mils;
    let laps = this.state.laps;
    laps.push(value);
    this.setState({ laps: laps });
  };
}

export default StopWatch;

component/stopwatchview.jsx

import React, { Component } from "react";
import "bootstrap/dist/css/bootstrap.css";
import "font-awesome/css/font-awesome.min.css";

class StopWatchView extends Component {
  constructor(props) {
    super(props);
  }
  render() {
    const heightWeidth = {
      fontSize: "xx-large",
    };
    return (
      <React.Fragment>
        <div class="card text-center border-success m-3">
          <div class="card-body">
            <div>
              <div className="badge badge-success mr-2">
                <span className="text-monospace" style={heightWeidth}>
                  {this.props.hrs}
                </span>
              </div>

              <div className="badge badge-success mr-2">
                <span className="text-monospace" style={heightWeidth}>
                  {this.props.min}
                </span>
              </div>

              <div className="badge badge-success mr-2">
                <span className="text-monospace" style={heightWeidth}>
                  {this.props.sec}
                </span>
              </div>

              <div className="badge badge-success ">
                <span className="text-monospace" style={heightWeidth}>
                  {this.props.mils}
                </span>
              </div>
            </div>
          </div>
        </div>
      </React.Fragment>
    );
  }
}

export default StopWatchView;
© 2020 GitHub, Inc.

component/stopwatchcontrolls.jsx

import React, { Component } from "react";

class StopWatchControl extends Component {
  constructor(props) {
    super(props);
  }

  interval = null;
  stopWatchStatuses = {
    PAUSED: "paused",
    STOPED: "stoped",
    RUNNING: "running",
  };

  render() {
    return (
      <React.Fragment>
        <div>
          <button
            className="btn btn-sm btn-success mr-2"
            onClick={this.stopWatchBtnEvent("start")}
          >
            <span className={this.stopWatchBtnCss("start")}></span>
          </button>

          <button
            className="btn btn-sm btn-success mr-2"
            onClick={this.stopWatchBtnEvent("pause")}
            disabled={this.props.pauseDisabled}
          >
            <span className={this.stopWatchBtnCss("pause")}></span>
          </button>
          <button
            className="btn btn-sm btn-success"
            onClick={this.stopWatchBtnEvent("laps")}
            disabled={this.props.lapsDisabled}
          >
            <span className={this.stopWatchBtnCss("laps")}>Laps</span>
          </button>
        </div>
      </React.Fragment>
    );
  }

  stopWatchBtnCss(btnType) {
    console.log("stopWatchBtnCss called");
    if (btnType === "start") {
      if (this.props.stopWatchStatus === this.stopWatchStatuses.STOPED) {
        return "fa fa-play";
      }
      if (
        this.props.stopWatchStatus === this.stopWatchStatuses.RUNNING ||
        this.props.stopWatchStatus === this.stopWatchStatuses.PAUSED
      ) {
        return "fa fa-stop";
      }
    }
    if (btnType === "pause") {
      if (this.props.stopWatchStatus === this.stopWatchStatuses.STOPED) {
        return "fa fa-pause disabled";
      }
      if (this.props.stopWatchStatus === this.stopWatchStatuses.RUNNING) {
        return "fa fa-pause";
      }
      if (this.props.stopWatchStatus === this.stopWatchStatuses.PAUSED) {
        return "fa fa-play";
      }
    }
    if (btnType === "laps") {
    }
  }
  stopWatchBtnEvent(btnType) {
    console.log("stopWatchBtnEvent called", this.stopWatchStatus);
    if (btnType === "start") {
      if (this.props.stopWatchStatus === this.stopWatchStatuses.STOPED) {
        return this.props.onstartStopWatch;
      }
      if (
        this.props.stopWatchStatus === this.stopWatchStatuses.RUNNING ||
        this.props.stopWatchStatus === this.stopWatchStatuses.PAUSED
      ) {
        return this.props.onStopStopWatch;
      }
    }
    if (btnType === "pause") {
      if (this.props.stopWatchStatus === this.stopWatchStatuses.STOPED) {
        return this.props.onPauseStopWatch;
      }
      if (this.props.stopWatchStatus === this.stopWatchStatuses.RUNNING) {
        return this.props.onPauseStopWatch;
      }
      if (this.props.stopWatchStatus === this.stopWatchStatuses.PAUSED) {
        return this.props.onstartStopWatch;
      }
    }
    if (btnType === "laps") {
      if (this.props.stopWatchStatus === this.stopWatchStatuses.RUNNING) {
        return this.props.onLapsClick;
      }
    }
  }
}

export default StopWatchControl;

component/stopwatchlapsview.jsx

import React, { Component } from "react";

class StopWatchLapsView extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
    };
  }
  render() {
    return (
      <React.Fragment>
        <div className="m-3">{this.renderLaps()}</div>
      </React.Fragment>
    );
  }
  renderLaps() {
    console.log("render laps called.");
    if (this.props.laps.length > 0) {
      return (
        <table className="table table-striped table-sm">
          <tbody>
            {this.props.laps.map((value, index) => (
              <tr>
                <th scope="row">{index + 1}</th>
                <td>{value}</td>
              </tr>
            ))}
          </tbody>
        </table>
      );
    } else {
      return "No Laps created yet.";
    }
  }
}

export default StopWatchLapsView;

You can find complete code for section 2 at github

Our final stop watch will look some thing like this

Final Stopwatch | techijournal.com
Final Stopwatch | techijournal.com

Conclusion

In this section of the post we learnt, how to lift state up in react js through stop watch example.

Thank’s Note

Thanks for spending you valuable time on this post hope this post was use full to you and you learned something new today. If you like our post please share our post.

Durgesh Kumar

He is the Founder of TechiJournal.com. And have 4+ years of experience as full-stack Java developer. He worked with many reputed product companies and would like to share his experience and knowledge through this blog. He works very hard to provide you with quality content. But as no one is perfect, If you feel that some improvement can be made then feel free to add it in the comment section. We look forward to it.

Leave a Reply