5 Top Most Commonly Used React Hooks — For Beginners

5 Top Most Commonly Used React Hooks — For Beginners

In this blog, we will understand the logic and uses of the top 5 React Hooks which are commonly used in React.js or Next.js applications.

Hooks are a powerful new feature introduced in React 16.8 that allows you to use state and other React features without writing a class. They let you “hook into” React state and lifecycle features from function components. This makes it possible to write simpler and more maintainable components.

  • They simplify component code: Hooks eliminate the need for class components in many cases, which can make your code cleaner and easier to read.
  • They enable state management in functional components: With hooks like useState, you can manage state directly within functional components, without needing to use lifecycle methods like componentDidMount or componentWillUnmount.
  • They promote code reuse: You can create custom hooks to encapsulate common logic and reuse it across different components. This makes your code more modular and easier to maintain.
  • They are backward compatible: Hooks are designed to work alongside existing React features, so you can gradually adopt them in your codebase without breaking anything.

Now we will discuss the top 5 hooks with their details and uses.

1. useState( )

useState() hook is used to add a state variable in your component which is used to update the state after the component is rendered. This hook can be used in the following scenarios.

  • Adding state to a component
  • Updating state based on the previous state
  • Updating objects and arrays in the state
  • Avoiding recreating the initial state
  • Resetting state with a key
  • Storing information from previous renders
  • Storing API results after the component is rendered

import { useState } from 'react';

const [count, setCount] = useState(0)        

Here we can break down the upper line of code.

  • count: count is a variable which contains the initial value of the state
  • setCount: setCount is a function that is used to update the value of state after the component is rendered
  • Initial Value: Inside useState() there is a number value “0” which is known as an initial value of count which is a state variable.

Here following is the example of a counter using useState() in React.js

import { useState } from 'react';

function Counter() {
  // Define state for the counter
  const [count, setCount] = useState(0);

  // Function to increment the counter
  const increment = () => {
    setCount(count + 1);
  };

  // Function to decrement the counter
  const decrement = () => {
    setCount(count - 1);
  };

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

export default Counter;        

This component maintains a state variable count using the useState hook, initialized to 0. It renders the current value of count, along with buttons to increment and decrement the counter. The increment and decrement functions modify the state by calling setCount with the updated value.

2. useEffect()

The useEffect() hook is a powerful tool in React's arsenal for managing side effects within functional components. Side effects are actions that modify the DOM, perform network requests, or interact with external systems outside React's component lifecycle. The following are some scenarios where we can use this hook.

  • Used to call API and set the response of API in the state.
  • Subscribe to changes in an external data source and update the component.
  • Used to handle timers in React.js like setTimeout(), setInterval(), clearInterval(), etc.
  • Modify DOM elements directly after rendering of the component.

import { useEffect } from "react";

useEffect(){() => {
....
// Logical code here
...
}, 
return () => {
...
// clean up state logic
... 
}
[]}
        

Here we can break down the upper useEffect() code.

  • Callback Function: The first phase of useEffect() contains a callback anonymous function which contains the logic that we want to perform after rendering of component
  • Return Statement: This optional return statement is a clean-up function that is used to reset or clear all states after useEffect() callback function is triggered.
  • Dependency Array: Dependency array is an important concept in useEffect() hook.

There are 3 concepts about dependency array

  • If there is no dependency array then useEffect() will go under an infinite loop and this will cause performance issues in web applications due to unnecessary renderings.
  • If you want to prevent an infinite loop of useEffect() then we will write an empty dependency array.
  • Sometimes we need to re-run useEffect() based on some state changes then we will pass that state in the dependency array.

useEffect(){() => {
....
// Logical code here
...
}, [count]}        

In this case, if count state changes then useEffect() will run again.

3. useRef()

It is a React Hook that lets you reference a value that’s not needed for rendering. It returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component. Following are some scenarios where we can use this hook.

  • Can be used to track the number of times a component has been rendered.
  • Can be used to store previous values in the form
  • Can be used to implement custom timers or animations
  • Can be used to access DOM elements directly like focus in the input field, to control the scrollings, to get dimensions of element, etc.

import { useRef } from "react";

const ref = useRef(null)        

Here we can break down the upper useRef() code:

  • ref: This is the name of the constant variable being declared. It's common to name a variable ref when it's intended to hold a reference to something.
  • Initial value: Initial value for ref is “null”, this means that ref currently does not have any kind of DOM reference.

Following is a basic example of useRef() using the input field:

import { useRef, useEffect } from 'react';

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

  useEffect(() => {
    // Focus on the input field when the component mounts
    inputRef.current.focus();
  }, []);

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

In this example, useRef is used to create a ref object (inputRef). This ref is then attached to an <input> element. Later, in the useEffect hook, the .focus() the method is called on inputRef.current, focusing on the input field when the component mounts.

4. useCallback()

It is a React Hook that helps improve performance by memoizing callback functions. In simpler terms, it caches a function and only returns a new version if its dependencies change. This prevents unnecessary re-renders of components that rely on that function. Following are some scenarios where we can use it.

  • When you pass a callback function to a child component as a prop.
  • When you use a callback function in an event handler or timer.
  • When a function’s re-creation triggers unnecessary re-renders.

import { useCallback } from "react";

const cachedFn = useCallback(()=> {
...
// your logical code
...
}, [])        

Here we can break down the upper code of useCallback()

  • Callback Function: Contains the logic which we want to perform.
  • Dependency Array: It works same as it works in useEffect() Hook.

Following are the benefits of using useCallback() Hook:

  • Improved performance: By reducing re-renders, your application runs smoother and feels more responsive.
  • Reduced memory usage: Caching the function saves memory compared to creating a new one on every render.
  • Cleaner code: It keeps your component code less cluttered by avoiding repetitive function definitions.

Following is the basic example of useCallback():

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

const Button = ({ onClick, children }) => {
  console.log("Button component rendered");
  return <button onClick={onClick}>{children}</button>;
};

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

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

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

export default App;        

In this example:

  • useCallback is used to memoize the increment function. This means that increment will only be recreated if any of its dependencies change. In this case, since the dependency array is empty ([]), increment will never be recreated after its initial creation.
  • The Button component receives onClick as a prop. By wrapping the increment function with useCallback, we ensure that onClick will always refer to the same function instance, preventing unnecessary re-renders of the Button component.
  • The Button component is rendered every time the state changes, but since increment is memoized, its reference remains constant, and the Button component doesn't re-render unnecessarily.

5. useMemo()

It is a React Hook that helps you cache the result of an expensive calculation between re-renders. In simpler terms, it remembers a value so you don’t have to calculate it again and again, which can improve the performance of your React application. Following are some scenarios where we can use useMemo()

  1. Expensive Calculation: You have a function that performs a complex or time-consuming calculation. This function might be called within your React component.
  2. Memoization: You wrap the function call in useMemo along with an array of dependencies. These dependencies are values that can affect the outcome of the calculation.
  3. Caching: The first time useMemo is called, it executes the function and stores the result in a cache.
  4. Re-renders: When your component re-renders, useMemo checks if the dependencies have changed. If they haven't, it simply returns the cached value without re-running the function. This saves time and resources.
  5. Updated Calculation: If any of the dependencies change, useMemo recognizes that the result might be different and re-runs the function to update the cached value.

import { useMemo } from "react";

const cachedValue = useMemo(calculateValue, [])        

Here we can break down the upper code of useMemo() Hook:

  • calculateValue: The function calculating the value that you want to cache. It should be pure, should take no arguments, and should return a value of any type. React will call your function during the initial render. On the next renders, React will return the same value if the dependency array states have not changed since the last render. Otherwise, it will call calculateValue, return its result, and store it so it can be reused later.
  • Dependency Array: It works the same as it works in useCallback() Hook.

Following are the benefits of using useMemo() Hook:

  • Improved performance: By avoiding unnecessary calculations, you can make your application run smoother and avoid lag.
  • Memory optimization: Memoizing results can help reduce memory usage by preventing duplicate calculations.
  • Cleaner code: useMemo helps you keep your component code cleaner and more maintainable by separating expensive calculations from the rendering logic.

Following is the basic example of useMemo()

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

const ExpensiveComponent = ({ data }) => {
  // A function that does some heavy computation based on the data
  const processData = (data) => {
    // Just a placeholder heavy computation
    console.log("Processing data...");
    return data.map(item => item * 2);
  };

  // Use useMemo to memoize the result of processData function
  const processedData = useMemo(() => processData(data), [data]);

  return (
    <div>
      <h2>Expensive Component</h2>
      <p>Processed Data: {processedData.join(', ')}</p>
    </div>
  );
};

const App = () => {
  const [data, setData] = useState([1, 2, 3, 4, 5]);

  const updateData = () => {
    setData(prevData => [...prevData, prevData.length + 1]);
  };

  return (
    <div>
      <button onClick={updateData}>Update Data</button>
      <ExpensiveComponent data={data} />
    </div>
  );
};

export default App;        

In this example:

  • We have an ExpensiveComponent that receives some data as props.
  • Inside ExpensiveComponent, we define a function processData() that does some heavy computation based on the data.
  • We use the useMemo() hook to memoize the result of processData() so that it only re-runs when the data prop changes.
  • In the App component, there is a button that, when clicked, updates the data passed to ExpensiveComponent. However, since processData() is memoized with useMemo(), it won't recalculate the processed data unless the data prop changes, optimizing performance.

Conclusion

In conclusion, React hooks have transformed how developers manage state and lifecycle in React applications. They offer a cleaner, more concise approach to writing components by encapsulating logic and promoting functional programming principles.

Despite a learning curve for those accustomed to class-based components, embracing hooks brings efficiency and scalability to projects. Mastering hooks is essential for staying current in modern web development.

So, explore, experiment, and unlock the full potential of React hooks to enhance your projects and streamline your development process.

Happy coding!

Purnima Vats

Ex-SWE fellow @Headstarter AI | Web Developer | Next.js | React.js | Student @Gargi College

9 个月

It was a great read. Thank you so much

回复
Asia Hassan

Biochemistry PhD Candidate || Passionate Educator || Front-End Developer || WordPress Web Developer || AI Enthusiast

1 年

An easy read. Thanks for this sir ??

Great insights for newcomers to React—understanding these hooks is definitely a game-changer for efficient coding!

要查看或添加评论,请登录

Hamza Siddique的更多文章

社区洞察

其他会员也浏览了