DEV Community

Cover image for React Hooks
Wafa Bergaoui
Wafa Bergaoui

Posted on

53 6 6 6 4

React Hooks

Introduction

React Hooks are one of the most important advancements in React, simplifying state management and enabling functional components to be just as powerful as class components. They address several challenges faced in previous versions of React and have become the standard for modern React development.


What Are React Hooks?

React Hooks are functions that let you use React features (like state and lifecycle methods) in functional components. They enable cleaner, simpler, and more readable code.


Why Were Hooks Introduced?

React Hooks solve several issues present with class components:

  • Complexity of Classes:
    Managing lifecycle and state with this in class components was often error-prone. Hooks simplify this.

  • Logic Reusability:
    Hooks make it easier to reuse logic across components without using HOCs or render props.

  • Improved Code Readability:
    Hooks streamline component code, making it shorter and easier to understand.

  • Incremental Adoption:
    Hooks can be used alongside class components, allowing gradual migration.


Principle React Hooks

React provides several hooks. Let’s explore each with examples and detailed explanations.


1. useState

Manages state in functional components.

Example:

import React, { useState } from 'react';

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

    return (
        <div>
            <p>Current Count: {count}</p>
            <button onClick={() => setCount(count + 1)}>Increment</button>
        </div>
    );
}

export default Counter;

Enter fullscreen mode Exit fullscreen mode

Explanation:

  • useState initializes the state variable count to 0.

  • setCount updates the state.


2. useEffect

Handles side effects like fetching data or updating the DOM.

Example:

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

function Timer() {
    const [time, setTime] = useState(0);

    useEffect(() => {
        const interval = setInterval(() => setTime(t => t + 1), 1000);
        return () => clearInterval(interval); // Cleanup on unmount
    }, []); // Run once on mount

    return <p>Elapsed Time: {time}s</p>;
}

export default Timer;

Enter fullscreen mode Exit fullscreen mode

Explanation:

  • Runs the effect once when the component mounts due to an empty dependency array [].

  • Cleans up the interval on unmount.


3. useContext

Accesses context values.

Example:

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

const ThemeContext = createContext('light');

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

    return <button style={{ background: theme === 'dark' ? '#333' : '#fff' }}>I am {theme} themed</button>;
}

function App() {
    return (
        <ThemeContext.Provider value="dark">
            <ThemedButton />
        </ThemeContext.Provider>
    );
}

export default App;

Enter fullscreen mode Exit fullscreen mode

Explanation:

  • useContext fetches the value from the nearest ThemeContext.Provider

4. useReducer

Manages complex state logic.

Example:

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('Unknown action type');
    }
}

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>
    );
}

export default Counter;

Enter fullscreen mode Exit fullscreen mode

Explanation:

  • useReducer manages complex state transitions with actions.

5. useRef

Persists values or references DOM nodes.

Example:

import React, { useRef } from 'react';

function FocusInput() {
    const inputRef = useRef();

    const focus = () => inputRef.current.focus();

    return (
        <div>
            <input ref={inputRef} placeholder="Click button to focus" />
            <button onClick={focus}>Focus Input</button>
        </div>
    );
}

export default FocusInput;

Enter fullscreen mode Exit fullscreen mode

Explanation:

  • The ref persists across renders and provides a reference to the DOM element.

6. useMemo

Memoizes expensive computations.

Example:

import React, { useMemo } from 'react';

function Factorial({ number }) {
    const factorial = useMemo(() => {
        const calculateFactorial = n => (n <= 1 ? 1 : n * calculateFactorial(n - 1));
        return calculateFactorial(number);
    }, [number]);

    return <p>Factorial of {number}: {factorial}</p>;
}

export default Factorial;

Enter fullscreen mode Exit fullscreen mode

Explanation:

  • useMemo avoids recalculating the factorial unless number changes.

7. useCallback

Memoizes a function.

Example:

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

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

    const increment = useCallback(() => setCount(prev => prev + 1), []);

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

export default Counter;

Enter fullscreen mode Exit fullscreen mode

Explanation:
Prevents unnecessary re-creation of increment on re-renders.


8. useLayoutEffect

Runs synchronously after DOM mutations (before painting).

Example:

import React, { useState, useLayoutEffect, useRef } from 'react';

function Box() {
    const boxRef = useRef();
    const [color, setColor] = useState('blue');

    useLayoutEffect(() => {
        console.log('Box dimensions:', boxRef.current.getBoundingClientRect());
    }, [color]);

    return (
        <div>
            <div ref={boxRef} style={{ width: 100, height: 100, background: color }}></div>
            <button onClick={() => setColor(color === 'blue' ? 'red' : 'blue')}>Toggle Color</button>
        </div>
    );
}

export default Box;

Enter fullscreen mode Exit fullscreen mode

Explanation:

  • useLayoutEffect ensures the DOM is measured before the browser paints.

Conclusion

React Hooks simplify component logic, promote code reusability, and enhance developer productivity. By understanding and effectively using hooks, you can write cleaner, more performant React applications.

Master these hooks, and you’ll unlock the full potential of React!

Sentry mobile image

Improving mobile performance, from slow screens to app start time

Based on our experience working with thousands of mobile developer teams, we developed a mobile monitoring maturity curve.

Read more

Top comments (5)

Collapse
 
kiketion profile image
Jorge Enrique Kike β€’

Thanks to the new compiler in the new version (19) of React we will not use useMemo and UseCallback anymore. In short, React 19 doesn't completely eliminate the need for memo , useMemo and useCallback , but it reduces their necessity

Collapse
 
wafa_bergaoui profile image
Wafa Bergaoui β€’

Thanks for pointing that out! You're rightβ€”React 19's new compiler reduces the need for useMemo and useCallback in many cases by handling re-renders more efficiently. That said, these hooks still have their uses, like optimizing expensive computations or memoizing functions in performance-critical scenarios.

Collapse
 
motuncoded profile image
Adijat Motunrayo Adeneye β€’

short and precise

Collapse
 
rickilloyd profile image
RickiLloyd β€’

React Hooks revolutionize the way we build React applications by enabling state and lifecycle management in functional components. They simplify code, promote reusability, and eliminate the need for class components, making development more intuitive and efficient. πŸš€πŸŽ―

Collapse
 
dexterhale profile image
Dexter Hale β€’

well explained!

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

πŸ‘‹ Kindness is contagious

Dive into an ocean of knowledge with this thought-provoking post, revered deeply within the supportive DEV Community. Developers of all levels are welcome to join and enhance our collective intelligence.

Saying a simple "thank you" can brighten someone's day. Share your gratitude in the comments below!

On DEV, sharing ideas eases our path and fortifies our community connections. Found this helpful? Sending a quick thanks to the author can be profoundly valued.

Okay