Skip to main content

Command Palette

Search for a command to run...

Hooked on React: The Power of React Hooks

Published
6 min read
Hooked on React: The Power of React Hooks

Ever wondered what react hooks are??

I'll try to explain React hooks simply!

React is a way to create computer programs that show things on the screen, like games or websites. React hooks are like little tools that help people who create these programs to do certain things more easily.

For example, there's a hook called useState helps you keep track of things that can change in your program, like a score in a game or a name in a form. Another hook called useEffect helps you do something when your program starts or when something changes, like showing a message when you win a game.

So, React hooks are like helpers that make it easier for people to create cool things on the computer screen!

There are several built-in hooks in React, including useState, useEffect, useContext, useReducer, and useCallback. Each hook serves a specific purpose:

  1. useState Hook

    It is used to add a state to functional components.

     import React, { useState } from 'react';
    
     function Counter() {
       const [count, setCount] = useState(0);
    
       return (
         <div>
           <p>You clicked {count} times</p>
           <button onClick={() => setCount(count + 1)}>
             Click me
           </button>
         </div>
       );
     }
    

    In the example above, we are using the useState hook to add state to our functional component. We define a state variable count and a function setCount to update that variable. We initialize count to 0 using useState(0). When the button is clicked, we call setCount with the new value of count.

  2. useEffect Hook

    It is used to add lifecycle methods to functional components, such as running code after a component mounts or updates.

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

    In the example above, we are using the useEffect hook to add a lifecycle method to our functional component. We pass a function to useEffect that sets the document title to the current count. The effect runs after every render.

  3. useContext Hook

    It is used to access data from a global context without prop drilling.

     import React, { useContext } from 'react';
     import { UserContext } from './UserContext';
    
     function UserProfile() {
       const user = useContext(UserContext);
    
       return (
         <div>
           <h2>{user.name}</h2>
           <p>Email: {user.email}</p>
         </div>
       );
     }
    

    In the example above, we are using the useContext hook to access data from a global context without prop drilling. We define a UserContext and pass it to the useContext hook in our functional component. This allows us to access the user object without passing it down through props.

  4. useReducer Hook

    It is a more powerful alternative to useState for managing complex state.

     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' })}>+</button>
           <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
         </div>
       );
     }
    

    In the example above, we are using the useReducer hook as an alternative to useState for managing complex states. We define an initial state and a reducer function that updates the state based on an action. We pass the reducer and initial state to the useReducer hook to get a state object and a dispatch function. We call dispatch with an action object to update the state.

  5. useCallback Hook

    It is used to memoize functions to prevent unnecessary re-renders.

     import React, { useState, useCallback } from 'react';
    
     function ItemList({ items }) {
       const [selectedItemId, setSelectedItemId] = useState(null);
    
       const handleItemClick = useCallback((itemId) => {
         setSelectedItemId(itemId);
       }, []);
    
       return (
         <div>
           <h2>Items</h2>
           <ul>
             {items.map((item) => (
               <li key={item.id} onClick={() => handleItemClick(item.id)}>
                 {item.name}
               </li>
             ))}
           </ul>
           {selectedItemId && (
             <p>You have selected item with ID {selectedItemId}</p>
           )}
         </div>
       );
     }
    

    In the example above, we have a ItemList component that displays a list of items and allows the user to select one of them. We define a state variable selectedItemId to keep track of the selected item.

    To handle item clicks, we define a handleItemClick function using the useCallback hook. This function updates the selectedItemId state with the ID of the clicked item. We pass an empty array as the second argument to useCallback to ensure that the function is only created once and not recreated on every render.

    We use the handleItemClick function in the onClick handler of each item in the list. When an item is clicked, the handleItemClick function is called with the ID of the clicked item, which updates the selectedItemId state.

    Finally, we render a message showing the ID of the selected item if there is one.

    Some more interesting examples of using React hooks:

    1. useMemo Hook:

      It allows you to memoize the result of computation so it doesn't get recalculated on every render, improving performance.

       import React, { useState, useMemo } from 'react';
      
       function ExpensiveCalculation({ x, y }) {
         const result = useMemo(() => {
           // Perform expensive calculation here
           return x * y;
         }, [x, y]);
      
         return (
           <div>
             The result of {x} * {y} is {result}.
           </div>
         );
       }
      

      In the example above, we are using the useMemo hook to memoize the result of an expensive calculation. We define a function that calculates the result based on x and y, and pass it to useMemo along with the dependencies x and y. This ensures that the result is only calculated when x or y changes, and not on every render.

    2. useRef Hook:

      It allows you to create a reference to a DOM element or a value that persists across renders.

       import React, { useRef } from 'react';
      
       function TextInputWithFocusButton() {
         const inputRef = useRef(null);
      
         function handleClick() {
           inputRef.current.focus();
         }
      
         return (
           <div>
             <input type="text" ref={inputRef} />
             <button onClick={handleClick}>Focus input</button>
           </div>
         );
       }
      

      In the example above, we are using the useRef hook to get a reference to the text input element. We define a handleClick function that calls the focus method on the input element. We pass the inputRef to the ref attribute of the input element to store a reference to it.

    3. useLayoutEffect Hook:

      It allows you to perform side effects synchronously after rendering, which can be useful for accessing DOM nodes or measuring their dimensions.

       import React, { useState, useLayoutEffect } from 'react';
      
       function LayoutEffectExample() {
         const [width, setWidth] = useState(0);
      
         useLayoutEffect(() => {
           const handleResize = () => setWidth(window.innerWidth);
           window.addEventListener('resize', handleResize);
           handleResize(); // Call once to get initial width
           return () => window.removeEventListener('resize', handleResize);
         }, []);
      
         return <div>The window width is {width}px.</div>;
       }
      

      In the example above, we are using the useLayoutEffect hook to update the width of the window dynamically. We define a handleResize function that updates the width state variable and add it as an event listener to the resize event on the window object. We call handleResize once to get the initial width.

      We pass an empty array as the second argument to useLayoutEffect to ensure that the effect is only run once when the component is mounted.

In addition to these built-in hooks, developers can also create custom hooks to encapsulate reusable logic.

Overall, hooks provide a more flexible and powerful way to manage state and lifecycle in React components, making it easier to write and maintain clean, efficient code.

More from this blog

Asritha's Blog

40 posts