Introduction

Ever since React introduced Function components, various hooks have been introduced. Remember the life cycle methods with class components?

A quick reminder,

An example with componentDidMount:

import React, { Component } from 'react'

class TestComponent extends Component {
  componentDidMount() {
    // Do something after the component mounts
    console.log('Component has mounted')
  }

  render() {
    return (
      <div>
        <h1>Hello, World!</h1>
      </div>
    )
  }
}

export default TestComponent

The componentDidMount method is called after the component has been mounted to the DOM. Inside the componentDidMount method, we can make API calls, set up event listeners etc. There are several other life cycle methods but we shall not dig into them as they are legacy.

Introducing React Hooks

React hooks were introduced in function components to replace the life cycle methods:

  1. The useState() hook

The useState hook is used to manage the state within a functional component. It takes an initial value and returns an array containing the current state and a function to update the state.

Example usage:

import React, { useState } from 'react'

function Example() {
  const [count, setCount] = useState(0)

  return (
    <div>
      <p>You clicked {count} times</p>

      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  )
}

1. The useState hook

The ** hook is used to manage state within a functional component. It takes an initial value and returns an array containing the current state and a function to update the state.

2. The useEffect hook

The useEffect hook is used to perform side effects within a functional component. It takes a function as its first argument that will be executed after every render.

Example usage:

import React, { useState, useEffect } from 'react'

function Example() {
  const [count, setCount] = useState(0)

  useEffect(() => {
    document.title = `You clicked ${count} times`
  })

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  )
}

The useEffect enables us to do DOM manipulation once the component has been rendered. We can also perform other side effects such as setting up event listeners etc.

An array of dependencies can be passed to the useEffect hook to prevent the execution of the hook unless the dependencies have changed:

import React, { useState, useEffect } from 'react'

function Example() {
  const [count, setCount] = useState(0)

  useEffect(() => {
    document.title = `You clicked ${count} times`
    // the count dependency ensures the hook is only run when the value changes in the next update
  }, [count])

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  )
}

3. The useContext hook

The useContext hook is used to access data from the context within a functional component.

Example usage:

import React, { useContext } from 'react'

const MyContext = React.createContext()

function MyComponent() {
  return (
    <MyContext.Provider value="Hello">
      <MyChildComponent />
    </MyContext.Provider>
  )
}

function MyChildComponent() {
  const value = useContext(MyContext)

  return <div>{value}</div>
}

4. The useReducer hook

The useReducer hook is used to manage complex stated within a component.

Example usage:

import React, { useReducer } from 'react'

const initialState = { count: 0 }

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 }
    case 'decrement':
      return { count: state.count - 1 }
    default:
      throw new Error()
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState)

  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </>
  )
}

5. The useMemo hook

The useMemo hook is used to memoize a value within a functional component. It takes a function and a dependency array as its arguments and returns a memoized value:

Example usage:

import React, { useMemo } from 'react'

function ExpensiveComponent({ value }) {
  const expensiveValue = useMemo(() => {
    // Some expensive computation
    return value * 2
  }, [value])

  return <div>{expensiveValue}</div>
}

The computation is “cached” and the expensiveValue can cause a re-render only if the value changes, otherwise the computation is never repeated and the “cached” value is used.

6. The useCallback hook

The useCallback hook is used to memoize a function within a functional component.

The useCallback hook takes a function and a dependency array as its arguments and returns a memoized function.

Example usage:

import React, { useState, useCallback } from 'react';

function ChildComponent({ onClick }) {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    setCount(count + 1);
    onClick();

You may follow me on Twitter where I tweet about interesting topics on software development and the current trends in technology.