Intro to React Hooks

Understanding React Hooks

React was initially released in 2013 as a class-based library. Hooks were not introduced until version 16.8 in 2018. Once introduced, React hooks with function components quickly became the default way of implementing React applications.

The shift was so pronounced that in 2023, the React team completely rewrote their documentation to reflect React as a hooks-based library: react.dev. Today, learning React essentially means learning React hooks and function components.

What Are Hooks?

A hook is a special function that allows you to "hook into" React state and lifecycle features within function components. React state refers to component-specific memory, which enables a component to retain values across renders. Lifecycle features refer to events such as mounting, rendering, updating, and unmounting.

Before hooks, only class components could manage state and lifecycle methods. Hooks introduced these capabilities into function components while simplifying their implementation. Essentially, hooks combine the benefits of object-oriented programming—such as encapsulation and abstraction—with an easy-to-follow functional approach.

For more information on why hooks were introduced, see the official documentation on Motivation for Hooks.

Using Hooks

React hooks follow a consistent naming convention: use<HookName>. For example, useState and useEffect. There are two fundamental rules for using hooks:

Commonly Used React Hooks

React provides several built-in hooks. Some are essential for daily use, while others are used for specific cases. Below is an overview of the most common hooks:

useState

Allows a component to manage internal state.


import { useState } from 'react';

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

  return (
    

Count: {count}

); }

useEffect

Runs side effects in function components (e.g., fetching data, event listeners).


import { useEffect } from 'react';

function Timer() {
  useEffect(() => {
    console.log("Component mounted!");

    return () => console.log("Component unmounted!");
  }, []);

  return 

Check the console for logs.

; }

useCallback

Optimizes performance by memoizing callback functions.


import { useCallback } from 'react';

function Parent() {
  const memoizedCallback = useCallback(() => {
    console.log("This function does not get recreated on every render");
  }, []);

  return ;
}
    

useContext

Allows components to access shared state without prop drilling.


import { useContext } from 'react';
const ThemeContext = React.createContext('light');

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return ;
}
    

useRef

Creates a mutable reference that persists across renders.


import { useRef } from 'react';

function InputFocus() {
  const inputRef = useRef(null);

  return (
    
); }

useReducer

An alternative to useState for managing complex state logic.


import { useReducer } from 'react';

function counterReducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(counterReducer, { count: 0 });

  return (
    

Count: {state.count}

); }

What You Have Learned

In this reading, you learned:

Further Exploration

To continue learning, check out:

Conclusion

Hooks revolutionized React by simplifying state management and lifecycle methods in function components. Understanding hooks is essential for modern React development.