useMemo hook

How to use the useMemo hook to save the result of a function without re-calculating it on every render.


Description

The useMemo hook will let you save the result of a function so that it will not be re-calculated on every render. Using it can considerably improve performances, especially if the function performs heavy operations.

Common use cases for this hook are:

  • Sorting arrays
  • Filtering arrays
  • Building objects


Usage

const result = useMemo(calculatorFn, dependencies);

The useMemo hook accepts two parameters: the calculator function and a list of dependencies. The calculator function accepts no parameters and should be pure and not be asynchronous. The new result of this function will be returned by the hook on the first render or whenever one of the listed dependencies changes.

You should use this hook whenever possible if you have to calculate the value of something through a function. Example:

// ❌ This will calculate the result on every render! Will make the CPU sad!
const activeUsers = users.filter((user) => user.active);
// ✅ Will be executed only when the "users" array changes
const activeUsers = useMemo(() => users.filter((user) => user.active), [users]);

Example: ordering users

In this example we will use the useMemo hook to alphabetically order a list of users.

import { useState, useMemo, html, defineWompo } from 'wompo';

// Randomly create 50 initial users.
const initialUsers = (() => {
  const users = [];
  for (let i = 0; i < 50; i++) {
    users.push({
      username: (Math.random() + 1).toString(36).substring(2), // random string
      id: i,
    });
  }
  return users;
})();

export default function OrderedUsersList() {
  const [users, setUsers] = useState(initialUsers);
  const alphabeticallyOrdered = useMemo(
    (users) => {
      const ordered = users.sort((a, b) => a.username.localeCompare(b.username));
      return ordered.map((user) => html`<li>${user.username}</li>`);
    },
    [users],
  );

  return html`
    <ul>
      ${alphabeticallyOrdered}
    </ul>
  `;
}

In the above example we first generated 50 random users, then in the OrderedUsersList component we sorted them inside the useMemo hook to save the sorted users list.
This is a simple example, but if you increase the number of generated users (so that the sorting operation will be more computationally expensive), you can really see how the useMemo hook can save your life(and the final user's life).