Learning React Hooks: Part 1: Components and State

Learning React Hooks

React hooks provide functionality to “hook into” React properties and life-cycle values outside of component classes.


Components and State

To understand why React hooks exist, it is important to start with a foundation of how components and their state work.

Consider the following example:

import React, {Component} from 'react';

class App extends Component {

  constructor(props) {
    super(props);

    this.state = {
      example: 1
    };
  }

  render() {
    return(
      <div>
          Show example value {this.state.example}!
      </div>
    );
  }
}

export default App;

Using a standard pattern of creating state for the component, the initial value is set during the constructor() function. Called as part of the component’s Mounting phase, the constructor() is called and then the render() function is.

During this initial phase (Mounting), the value of this.state.example is set and then is used during the initial render().

Now consider this more advanced example:

import React, {Component} from 'react';

class App extends Component {

  constructor(props) {
    super(props);

    this.state = {
      example: 1
    };

  }

  render() {
    return(
      <div onClick={() => this.setState({example: this.state.example + 1})}>
          Show example value {this.state.example}!
      </div>
    );
  }
}

export default App;

The above code expands on the initial example through using the onClick property and using an arrow function. Within this, the function this.setState() is called. Inherited from Component, this function queues possible state changes and then calls render() if so.

The use of the setState() function also happens as part of the Updating phase.

The Mounting phase creates the initial structure and values. The Updating phase, as it names implies, updates the component, most often through calls to this.setState() internally as part of other events such as a user clicking.

The use of the setState() function also merges the new changes with any possible values. When passed an object literal, it updates any new values passed to it based on the key-value pairs passed to it. All other existing values are retained.

Consider this example with multiple state values:

import React, {Component} from 'react';

class App extends Component {

  constructor(props) {
    super(props);

    this.state = {
      example: 1,
      secondExample: 2
    };

  }

  render() {
    return(
      <div onClick={() => this.setState({example: this.state.example + 1})}>
        <p>Show example value {this.state.example}!</p>
        <p>Show second example value {this.state.secondExample}!</p>
      </div>
    );
  }
}

export default App;

Lifting State

Creating complex projects with React often present the need to have one or more components share initial or run-time data. In these cases, the state is “lifted” to another, parent component that centrally handles state data.

Functions that change the central state data call “up” to their parent component. Data is passed “down” and function calls go “up.”

Consider the following “lifting state” example:

import React, {Component} from 'react';

class Example extends Component {
  render() {
    return (
      <p 
        onClick={() => this.props.increaseValue()}>
          Show example value {this.props.exampleValue}!
      </p>
    );
  }
}

class App extends Component {

  constructor(props) {
    super(props);

    this.state = {
      example: 1,
      secondExample: 2
    };

  }

  increaseValue = () => {
    this.setState({example: this.state.example + 1});
    console.log("Testing!");
  }

  render() {
    return(
      <div>
        <Example 
          increaseValue={this.increaseValue} 
          exampleValue={this.state.example} 
        />
      </div>
    );
  }
}

export default App;

In the above code, the component <Example> is passed two properties: a function and the current value of this.state.example. Each time it is rendered, it uses these values.

The phrasing “each time it is rendered” is important because any clicking on its paragraph element will call the increaseValue() function, which is part of the <App> component. In turn, its internal function calls setState(). Because state data has changed, its own render() function is called, which means new values are passed to <Example>. And thus, <Example> then shows the new values.

Any click on <Example>, then, triggers a function call “up” to its parent, which, in turn, re-renders and thus, ultimately, re-renders <Example> itself. The state was “lifted” into the parent, <App>, but the same reaction happens: clicking on the text increases the internal this.state.example value.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.