reactjs-interview-questions icon indicating copy to clipboard operation
reactjs-interview-questions copied to clipboard

Please add more detail on useMemo hooks?

Open likithsai opened this issue 3 years ago • 4 comments

Hi Sir, Can you add a new point on how and why useMemo() is used in ReactJS with example. This is an important concept and without this, you can't undestand pure components.

likithsai avatar Apr 04 '22 11:04 likithsai

useMemo is a React hook that is used to optimize the performance of a component by memoizing (caching) the values of expensive function calls. It takes in two arguments: a function and an array of dependencies. The function will only be re-evaluated if one of the dependencies has changed.

For example, let's say you have a component that renders a list of items from an array. You want to add some additional logic to each item in the list, but this logic is expensive and you don't want it to run every time the component renders. You can use useMemo to memoize this logic so that it only runs when one of the dependencies changes:

macck7 avatar Jan 12 '23 15:01 macck7

image

macck7 avatar Jan 12 '23 15:01 macck7

useMemo hook definiton:

useMemo is a React hook that allows you to memoize (or cache) the result of a function so that it only gets recomputed when the inputs to that function change, useMemo basically optimizes the performance of a component.

Understanding useMemo with an easy example function MyComponent({ a, b }) { const result = useMemo(() => { console.log('computing result') return a + b }, [a, b]) return <div>The result is {result}</div> In this example, useMemo is used to memoize the result of adding a and b. The memoized value of result will only be recomputed if either a or b changes between renders.

Hope this helps

Umair2516Khan avatar Apr 22 '23 12:04 Umair2516Khan

Performance Hooks:

A common way to optimize re-rendering performance is to skip unnecessary work. For example, you can tell React to reuse a cached calculation or to skip a re-render if the data has not changed since the previous render.

To skip calculations and unnecessary re-rendering, use one of these Hooks:

  • useMemo lets you cache the result of an expensive calculation.
  • useCallback lets you cache a function definition before passing it down to an optimized component.

Both hooks are used to increase the performance of our application.

Let's take an example:

const App = () => {
  const [count, setCount] = useState(0);
  const [todos, setTodos] = useState([]);
  const calculation =**expensiveCalculation(count);**

  const increment = () => {
    setCount((c) => c + 1);
  };
  const addTodo = () => {
    setTodos((t) => [...t, "New Todo"]);
  };

  return (
    <div>
      <div>
        <h2>My Todos</h2>
        {todos.map((todo, index) => {
          return <p key={index}>{todo}</p>;
        })}
        <button onClick={addTodo}>Add Todo</button>
      </div>
      <hr />
      <div>
        Count: {count}
        <button onClick={increment}>+</button>
        <h2>Expensive Calculation</h2>
        {calculation}
      </div>
    </div>
  );
};

const expensiveCalculation = (num) => {
  console.log("Calculating...");
  for (let i = 0; i < 1000000000; i++) {
    num += 1;
  }
  return num;
};

Here expensiveCalculation function will be called on every render even it does not has any direct relation to todos, it will cause performance issue.

Solution: useMemo hook

useMemo hook:

  • useMemo lets you cache the result of an expensive calculation between re-renders.
  • useMemo returns a memoized value
import { useState, useMemo } from "react";
const App = () => {
  const [count, setCount] = useState(0);
  const [todos, setTodos] = useState([]);
  const calculation = **useMemo(() => expensiveCalculation(count), [count]);**

  const increment = () => {
    setCount((c) => c + 1);
  };
  const addTodo = () => {
    setTodos((t) => [...t, "New Todo"]);
  };

  return (
    <div>
      <div>
        <h2>My Todos</h2>
        {todos.map((todo, index) => {
          return <p key={index}>{todo}</p>;
        })}
        <button onClick={addTodo}>Add Todo</button>
      </div>
      <hr />
      <div>
        Count: {count}
        <button onClick={increment}>+</button>
        <h2>Expensive Calculation</h2>
        {calculation}
      </div>
    </div>
  );
};

const expensiveCalculation = (num) => {
  console.log("Calculating...");
  for (let i = 0; i < 1000000000; i++) {
    num += 1;
  }
  return num;
};

Now expensiveCalculation function will only be called at first render and on every count change.

Muhammad-Faraz-Ali avatar Jun 08 '23 06:06 Muhammad-Faraz-Ali