Step 11

We can now generate the cycles but we need to reload (re-render) the Output component to show the new cycles.

This is where "states" come in!

We learned that props refer to data passed from parent components to child components.

The props represent "read-only" data that are meant to be immutable.

So if you are a component, should not modify props that you receive!

A component's state, on the other hand, represents mutable data. The "state" ultimately affects what is rendered on the page.

A component's state is managed internally by the component itself and is meant to change over time, commonly due to user input (e.g., clicking on a button on the page).

By having a component manage its own state, any time there are changes made to that state, React will know and automatically make the necessary updates to the page.

This is one of the key benefits of using React to build UI components:

When it comes to re-rendering the page, we just have to think about updating state.

  • We don't have to keep track of exactly which parts of the page changed each time there are updates.
  • We don't need to decide how we will efficiently re-render the page.
  • React compares the previous state and new state, determines what has changed, and makes these decisions for us.
  • This process of determining what has changed in the previous and new states is called Reconciliation.

Update the constructor of App component:

constructor(props) {
  super(props);
  this.state = {
    cycles: [
      "11:44 PM",
      "1:14 AM",
      "2:44 AM",
      "4:14 AM",
      "5:44 AM",
      "7:14 AM",
    ],
  };
}

When you update the state, you must use the function setState (which is inherited from Component class).

We can technically update the state directly, but that way React will not know we have updated it!

The simplest way to use setState is to pass an object to it, and the object will be merged into the current state to form the new state.

this.setState({ cycles: [/* new values */] })

Let's update the calcCycles method to update the state:

calcCycles() {
  // get current time
  let now = Date.now(); // in milliseconds
  let minute = 60 * 1000; // milliseconds
  let cycle = now;
  const cycles = new Array(this.state.cycles.length);

  // allow 14 minutes to fall sleep
  cycle += 14 * minute;

  // calculate 6 sleep cycles (each 90 minutes)
  for (let i = 0; i < 6; i++) {
    cycle += 90 * minute;

    // update the sleep cycles
    cycles[i] = new Date(cycle).toLocaleTimeString([], {
      hour: "2-digit",
      minute: "2-digit",
    });
  }

  // print cycles for sanity check
  console.log(cycles);

  // update state
  this.setState({ cycles: cycles });
};

Aside: Don't forget to update the props passed to Output component:

- <Output cycles={this.cycles} />
+ <Output cycles={this.state.cycles} />

Save the file and reload the app. Click on the zzz button. The cycles must be updated in the page!