Understanding useState Hook in React

by Gaurav Jassal on 2018-11-03

React is the most powerful UI library. The team is improving performance and the development experience every day by adding amazing features. Recently the team has added awesome feature called Hooks.

Hooks will try to solve few issues with react component class. Take an example we start with a small component class and as the component grows and we start adding more complex logic in constructor and other lifecycle methods like componentDidMount, componentDidUnmount etc we end up with a huge component file and is difficult to maintain. Sometimes you start the component as functional stateless component by later require to add stateful component you will start add context, refs or lifecycle methods. Then you endup converting the stateless component into class component.

React Conf 2018

At React Conf 2018, Sophie Alpert and Dan Abramov introduced Hooks, followed by Ryan Florence demonstrating how to refactor an application to use them. Watch the video here:

What are Hooks

Hooks are a new feature proposal that lets you use state and other React features without writing a class. They’re currently in React v16.7.0-alpha and being discussed in an open RFC.

This new function useState is the first “Hook” we’ll learn about, but this example is just a teaser. Don’t worry if it doesn’t make sense yet!

Let understand this with an example with two components class babed component vs using hooks. This example renders a counter. When you click the button, it increments and decrements the value:

Class based component

import React, { Component } from 'react'

export default class CounterComponent extends Component {
  constructor(props) {
    super(props)
    this.state = {
      counter: 0,
    }
  }
  increment = value => {
    this.setState((state, props) => {
      return { counter: state.counter + 1 }
    })
  }

  decrement = value => {
    this.setState((state, props) => {
      return { counter: state.counter - 1 }
    })
  }

  render() {
    return (
      <div>
        <div>
          <button onClick={() => this.increment()}> + Increment Counter</button>
          <button onClick={() => this.decrement()}> - Decrement Counter</button>
        </div>
        <div>Current Counter: {this.state.counter}</div>
      </div>
    )
  }
}

Let’s rewrite the same component using useState Hook

import React, { useState } from 'react'
export default function counterHook() {
  const [count, setCount] = useState(0)
  return (
    <div>
      <div>
        <button onClick={() => setCount(count + 1)}>
          {' '}
          + Increment Counter
        </button>
        <button onClick={() => setCount(count - 1)}>
          {' '}
          - Decrement Counter
        </button>
      </div>
      <div>Current Counter: {count}</div>
    </div>
  )
}

The useState hook lets you add state to function components. We call it inside a function component to add some local state to it. React will preserve this state between re-renders. useState returns a pair: the current state value and a function that lets you update it. You can call this function from an event handler or somewhere else. It’s similar to this.setState in a class, except it doesn’t merge the old and new state together.

In class based component, the state is always an object. You can store properties on that object.

With hooks, the state doesn’t have to be an object. It can be any type you want – an array, a number, a boolean, a string, etc. Each call to useState creates a single piece of state, holding a single value.