Skip to main content

React Hooks: A Deep Dive

React Hooks: A Deep Dive

React Hooks are a relatively new addition to React library. They allow us to use state and other React features without having to use class components or write boilerplate code.In this article, we will take a deep dive into most commonly used React Hooks are shown in table of contents.

useState

The useState Hook allows us to add state to our functional components. It takes an initial state value as a parameter and returns an array containing the current state value and a function to update the state.

Example:


                import React, { useState } from 'react';

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

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

                  return (
                    <div>
                      <p>You clicked {count} times</p>
                      <button onClick={increment}>Click me</button>
                    </div>
                  );
                }
            
        

useEffect

The useEffect Hook allows us to perform side effects in our functional components. It takes a function as a parameter and runs it after the component has been rendered.

Example:


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

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

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

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

                  return (
                    <div>
                      <p>You clicked {count} times</p>
                      <button onClick={increment}>Click me</button>
                    </div>
                  );
                }
            
        

useContext

The useContext Hook allows us to use context in our functional components. It takes a context object as a parameter and returns the current context value.

Example:


                import React, { useContext } from 'react';

                const ThemeContext = React.createContext('light');

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

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

                  return (
                    <div>
                      <button style={{ background: theme === 'dark' ? 'black' : 'white', color: theme === 'dark' ? 'white' : 'black' }}>
                        {theme === 'dark' ? 'Dark' : 'Light'}
                      </button>
                    </div>
                  );
                }
            
        

useReducer

The useReducer Hook allows us to use a reducer function to manage state in our functional components. It takes a reducer function and an initial state value as parameters and returns an array containing the current state value and a dispatch function to update the state.

Example:


                import React, { useReducer } from 'react';

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

                function Counter() {
                  const [count, dispatch] = useReducer(reducer, 0);

                  return (
                    <div>
                      <p>You clicked {count} times</p>
                      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
                      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
                    </div>
                  );
                }
            
        

useCallback

The useCallback Hook allows us to memoize a function and prevent it from being recreated on every render. It takes a function and an array of dependencies as parameters and returns a memoized function.

Example:


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

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

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

                  return (
                    <div>
                      <p>You clicked {count} times</p>
                      <button onClick={increment}>Click me</button>
                    </div>
                  );
                }
            
        

useMemo

The useMemo Hook allows us to memoize a value and prevent it from being recalculated on every render. It takes a function and an array of dependencies as parameters and returns a memoized value.

Example:


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

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

                  const doubleCount = useMemo(() => {
                    return count * 2;
                  }, [count]);

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

useRef

The useRef Hook allows us to create a mutable variable that persists across renders. It returns an object with a current property that we can set and get the value of.

Example:


                import React, { useRef } from 'react';

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

                  const handleSubmit = (event) => {
                    event.preventDefault();
                    alert(inputRef.current.value);
                  };

                  return (
                    <form onSubmit={handleSubmit}>
                      <input type="text" ref={inputRef} />
                      <button type="submit">Submit</button>
                    </form>
                  );
                }
            
        

useLayoutEffect

The useLayoutEffect Hook is similar to useEffect, but it runs synchronously after all DOM mutations are processed. This makes it useful for measuring layout and performing animations.

Example:


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

                function App() {
                  const [width, setWidth] = useState(0);

                  useLayoutEffect(() => {
                    setWidth(document.documentElement.clientWidth);
                  }, []);

                  return (
                    <div>
                      <p>Window width: {width}</p>
                    </div>
                  );
                }
            
        

useImperativeHandle

The useImperativeHandle Hook allows us to customize the instance value that is exposed to parent components when using ref. It takes a ref and a function that returns an object as parameters.

Example:


                import React, { useRef, useImperativeHandle } from 'react';

                function FancyInput(props, ref) {
                  const inputRef = useRef();

                  useImperativeHandle(ref, () => ({
                    focus: () => {
                      inputRef.current.focus();
                    }
                  }));

                  return <input ref={inputRef} />;
                }

                FancyInput = React.forwardRef(FancyInput);

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

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

                  return (
                    <div>
                    <FancyInput ref={inputRef} />
                    <button onClick={handleClick}>Focus</button>
                    </div>
                  );
                }
            
        

useMemo vs useCallback

Both useMemo and useCallback allow us to memoize values and functions, respectively, and prevent them from being recalculated or recreated on every render. The difference is that useMemo returns a memoized value, while useCallback returns a memoized function.

Use useMemo when:

  • You need to memoize a value, not a function
  • The calculation is expensive and you want to prevent it from being recalculated on every render
  • The value is not dependent on any prop or state changes

Use useCallback when:

  • You need to memoize a function, not a value
  • The function is expensive to create and you want to prevent it from being recreated on every render
  • The function is passed down to child components as a prop and you want to prevent unnecessary renders
  • The function relies on some dependencies, such as props or state, that may change frequently

useDebugValue

The useDebugValue Hook allows us to display custom debugging information for a Hook in the React DevTools. It takes a value as parameter and a formatting function that formats the value for display.

Example:


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

                function useCounter(initialValue) {
                  const [count, setCount] = useState(initialValue);
                  useDebugValue(count, count => `Count: ${count}`);
                  return [count, () => setCount(count + 1)];
                }

                function App() {
                  const [count, increment] = useCounter(0);

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

Custom Hooks

Custom Hooks are a way to reuse stateful logic across components. They are normal JavaScript functions that use one or more of the built-in Hooks and return a stateful value and/or functions to update that value.

Example:


                import { useState, useEffect } from 'react';

                function useMousePosition() {
                  const [position, setPosition] = useState({ x: 0, y: 0 });

                  function handleMouseMove(e) {
                    setPosition({ x: e.clientX, y: e.clientY });
                  }

                  useEffect(() => {
                    window.addEventListener('mousemove', handleMouseMove);
                    return () => {
                      window.removeEventListener('mousemove', handleMouseMove);
                    };
                  }, []);

                  return position;
                }

                function App() {
                  const { x, y } = useMousePosition();

                  return (
                    <div>
                      <p>The mouse position is ({x}, {y})</p>
                    </div>
                  );
                }
            
        

Conclusion

React Hooks are a powerful and flexible way to manage state and side effects in functional components. They allow us to write more concise and reusable code, and to share stateful logic between components. By using the built-in Hooks and creating custom Hooks, we can create complex and dynamic user interfaces with ease.

React Hooks are a powerful and flexible way to manage state and side effects in functional components. They allow us to write more concise and reusable code, and to share stateful logic between components. By using the built-in Hooks and creating custom Hooks, we can create complex and dynamic user interfaces with ease.

While Hooks are a great addition to React, they are not always necessary or appropriate. Class components still have their place, especially in legacy code or in cases where we need to leverage their full lifecycle methods or access to the DOM. Additionally, Hooks are not a replacement for good programming practices, such as code organization, separation of concerns, and testing.

It is important to use Hooks responsibly and to understand their limitations and tradeoffs. By doing so, we can take advantage of their benefits and create better React applications.

© 2023 React Hooks Deep Dive

Comments

Popular posts from this blog

How to Create a Circular Scroll Progress with HTML, CSS & JavaScript

See the Pen How to Create a Circular Scroll Progress with HTML, CSS & JavaScript by Mushtaq Ahmad ( @MushtaqPhysicist ) on CodePen . How to Create a Circular Scroll Progress with HTML, CSS & JavaScript In this guide, we will explore process of using HTML, CSS, and JavaScript to design a circular scroll progress indicator. This type of indicator displays percentage of a webpage that has been scrolled. Specifically, we will create a circular indicator and position it in bottom right corner of webpage. The indicator's fill level will correspond to amount of page that has been scrolled. HTML Copy Code <!DOCTYPE html> <html lang="en"> <head> <title>Scroll Percentage</title> <!-- Stylesheet --> <link rel="stylesheet" href="style.css"> </head> <body>...

Find Your Location using HTML, CSS & JavaScript

See the Pen Untitled by Mushtaq Ahmad ( @MushtaqPhysicist ) on CodePen . Find Your Location using HTML, CSS & JavaScript It is against policy to access Geolocation in Blogger.com . However, you can still find your location by clicking on CodePen button and then clicking the Get Location button to retrieve your location data Source Code HTML Copy Code <div class="container"> <h1>Find Your Location</h1> <p>Your location: <span id="location"></span></p> <button id="getLocation">Get Location</button> </div> CSS Copy Code body { font-family: Arial, sans-serif; margin: 0; padding: 0; background-color: #f5f5f5; } .container { max-width: 800px; margin: 0 auto; padding: 50px; background-color: #fff; border...

Develop a Quiz App with Timer using HTML CSS & JavaScript

Develop a Quiz App with Timer using HTML CSS & JavaScript See the Pen Create a Quiz App with Timer using HTML CSS & JavaScript by Mushtaq Ahmad ( @MushtaqPhysicist ) on CodePen . In this article you’ll learn how to Create a Quiz Application with Timer using HTML CSS & JavaScript. The Quiz App with Timer program consists of three layers or boxes that are sequentially displayed when a specific button is clicked. Initially, the webpage displays a "Start Quiz" button, which, upon clicking, triggers a pop-up animation displaying an info box. The info box contains the rules of the quiz and two buttons labeled "Exit" and "Continue." Clicking on the "Exit" button hides the info box, while clicking on "Continue" button displays the Quiz Box. Within the Quiz Box, there is a header with a title on the left side and a timer box on the right side. The timer starts at 15 seconds and decremen...