useCallback hook

How to use the useCallback hook to cache functions and improve performance.


Description

The useCallback hook is a hook that lets you save a function definition across re-renders, so that it'll always keep the same reference to it.
Why is it useful? Because in javascript two function declarations are not considered equal:

function() { } === function() { } // false

const a = () => { }
a === a // true

So, for example, a useful case whre you can use it, is when a callback function is passed through the props of another component: if you don't use the useCallback hook, the child component will re-render every time the parent component changes, because the two functions will be considered different.

Note: This consideration doesn't apply to events, because events are stored in a simple variable and will not cause an add/removal of event listeners, so it's not computationally expensive: it's more expensive to store the callback and get it back every time.


Usage

const callback = useCallback(callbackDefinition, dependencies);

The hook will cache the callbackDefinition function and alway return the same value on every render, without re-initializing the function every time.
The hook accepts two parameters: a callback that can be any function declaration, and a list of dependencies. The dependecies are optional, but if they are set, the hook will check if any of them changed, and if it happened, it will re-build the function and return the new value.


Example

A basic example is using the useCallback hook to pass it to another component as a parement, so that useless re-renderings are avoided.

import { useCallback, defineWompo, html } from 'wompo';
import UserForm from './UserForm';

export default function User({ userId }) {
  const submitData = useCallback(
    (data) => {
      fetch(`/udpate/user/${userId}`, { method: 'POST', body: data });
    },
    [userId],
  );

  return html`<${UserForm} onSubmit=${submitData} />`;
}

defineWompo(Component);

In this example, the UserForm component will not re-render every time that the User component renders.