DEV Community

Cover image for You Should know 7 Popular React Hooks for State Management, Side Effects, and More
msbala
msbala

Posted on • Updated on

You Should know 7 Popular React Hooks for State Management, Side Effects, and More

React Hooks are a popular feature introduced in React 16.8 that allow developers to use state and other React features without writing class components. Here are some of the most popular React Hooks.

1. useState

useState is one of the most commonly used React Hooks. It allows you to add state to a functional component, which can then trigger re-renders when it changes.

import React, { useState } from 'react';

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

  function increment() {
    setCount(count + 1);
  }

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

In this code snippet, we use the useState hook to declare a state variable called count, which is initially set to 0. We also declare a function called setCount which we use to update the value of count.

We then define a function called increment which simply calls setCount with the new value of count + 1.

Finally, we render the current value of count and a button that, when clicked, calls the increment function.

2. useEffect

useEffect is another popular hook that lets you perform side effects, like fetching data, setting up subscriptions, or updating the DOM, in a functional component.

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

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

  useEffect(() => {
    const timer = setInterval(() => {
      setCount(count + 1);
    }, 1000);

    return () => clearInterval(timer);
  }, [count]);

  return (
    <div>
      <p>Timer: {count} seconds</p>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

In this code snippet, we use the useEffect hook to start a timer that increments the value of count by 1 every second using setInterval.

We pass an empty array [] as the second argument to useEffect to tell React that we only want to run this effect once, when the component mounts. We also return a cleanup function that clears the interval when the component unmounts.

We also pass [count] as the second argument to useEffect to tell React to run this effect every time count changes. This will ensure that the timer updates the UI with the latest value of count.

Finally, we render the current value of count in the UI.

3. useContext

useContext lets you consume context created by a parent component, allowing you to share data between components without having to pass props down through multiple levels.

import React, { createContext, useContext } from 'react';

const MyContext = createContext();

function App() {
  return (
    <MyContext.Provider value="Hello, World!">
      <MyComponent />
    </MyContext.Provider>
  );
}

function MyComponent() {
  const value = useContext(MyContext);

  return <p>{value}</p>;
}

Enter fullscreen mode Exit fullscreen mode

In this code snippet, we define a new context using createContext and store it in a variable called MyContext.

We then define a App component that wraps a child component (MyComponent) in the MyContext.Provider component. We pass a value of "Hello, World!" to the provider, which will be the default value of the context.

Finally, we define a MyComponent component that uses the useContext hook to retrieve the value of MyContext. We then render this value in a p element.

When MyComponent is rendered inside App, it will receive the value of MyContext from the provider and render "Hello, World!" in the UI.

4. useReducer

useReducer is a more powerful alternative to useState, allowing you to manage more complex state changes in your components.

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 (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

In this code snippet, we use the useReducer hook to manage a state variable called count that is initially set to 0. We define a reducer function that takes a state and an action as arguments, and returns a new state based on the action.

We define two actions: increment, which increments the count by 1, and decrement, which decrements the count by 1. If the reducer receives an unknown action, it throws an error.

We then define a Counter component that uses useReducer to initialize the state with initialState and the reducer function. We render the current value of count and two buttons that dispatch the increment and decrement actions, respectively.

When the buttons are clicked, they call the dispatch function with the appropriate action type, which causes the reducer to update the state accordingly. The UI is updated with the new value of count by re-rendering the component.

5. useCallback

useCallback is a hook that lets you memoize a function so that it only changes when its dependencies change. This can help improve performance by reducing unnecessary re-renders.

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

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

  const increment = useCallback(() => {
    setCount(count + 1);
  }, [count]);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

In this code snippet, we use the useCallback hook to create a memoized version of the increment function. This means that the increment function will only be re-created when the count state changes.

We declare a count state variable using useState, and define the increment function using useCallback. The increment function simply calls setCount with the new value of count + 1.

We then render the current value of count and a button that, when clicked, calls the increment function.

By using useCallback, we can avoid unnecessary re-renders of the component, since the increment function will not change unless count changes. This can help improve performance in some cases.

6. useMemo

useMemo is similar to useCallback, but it memoizes a value instead of a function. This can be useful for expensive calculations that don't need to be re-calculated on every render.

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

function Square({ value }) {
  return <button>{value}</button>;
}

function Board() {
  const [squares, setSquares] = useState(Array(9).fill(null));

  const handleClick = useMemo(() => {
    return (i) => {
      const newSquares = [...squares];
      newSquares[i] = 'X';
      setSquares(newSquares);
    };
  }, [squares]);

  return (
    <div>
      <div className="board-row">
        <Square value={squares[0]} onClick={() => handleClick(0)} />
        <Square value={squares[1]} onClick={() => handleClick(1)} />
        <Square value={squares[2]} onClick={() => handleClick(2)} />
      </div>
      <div className="board-row">
        <Square value={squares[3]} onClick={() => handleClick(3)} />
        <Square value={squares[4]} onClick={() => handleClick(4)} />
        <Square value={squares[5]} onClick={() => handleClick(5)} />
      </div>
      <div className="board-row">
        <Square value={squares[6]} onClick={() => handleClick(6)} />
        <Square value={squares[7]} onClick={() => handleClick(7)} />
        <Square value={squares[8]} onClick={() => handleClick(8)} />
      </div>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

In this code snippet, we use the useMemo hook to memoize the handleClick function. The handleClick function updates the state of the squares array when a square on the game board is clicked.

We declare a squares state variable using useState, and define the handleClick function using useMemo. The handleClick function creates a new copy of the squares array with the clicked square updated to 'X', and then sets the state of squares to the new array.

We then render the game board by mapping over the squares array and rendering a Square component for each item in the array. The Square component receives a value prop and an onClick prop, which is set to the memoized handleClick function with the appropriate index.

By using useMemo, we can memoize the handleClick function so that it doesn't get re-created on every render of the component. This can help improve performance in some cases.

7. useRef

useRef allows you to create a mutable reference that persists across renders. This can be useful for storing mutable values, like a reference to a DOM element.

import React, { useRef } from 'react';

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

  const handleClick = () => {
    inputRef.current.focus();
  };

  return (
    <div>
      <input type="text" ref={inputRef} />
      <button onClick={handleClick}>Focus Input</button>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

In this code snippet, we use the useRef hook to create a reference to the text input element. We then use this reference to set focus to the input element when a button is clicked.

We declare an inputRef variable using useRef, and assign it to the ref attribute of the text input element. We then define a handleClick function that calls the focus() method of the inputRef object to set focus to the input element.

We render the text input element and a button that, when clicked, calls the handleClick function.

By using useRef, we can create a reference to a DOM element and access its properties and methods. This can be useful in cases where we need to interact with a specific DOM element, such as setting focus to an input field.

Conclusion

These are just a few of the most commonly used React Hooks. There are many other hooks available in the React ecosystem, and new ones are being created all the time.

Top comments (0)