Fecha publicación: 5 feb 2025

Bye useCallback

En ejemplo anteriores vimos como instalar el compilador de React y como optimizar un componente con React.memo.

Vamos ahora a ver si también podemos quitarnos de enmedio useCallback.

Empezamos como antes, deshabilitamos el compilador

./vite.config.ts

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

// https://vite.dev/config/
export default defineConfig({
  plugins: [
    react(
+     /*
      {
      babel: {
        plugins: [["babel-plugin-react-compiler", { target: "19" }]],
      },
    }
+    */
    ),
  ],
});

Y ahora vamos a por el fichero demo.tsx, y vamos a probar el siguiente escenario:

./src/demo.tsx

import React from "react";

interface Props {
  onReset: () => void;
}

const ResetValue: React.FC<Props> = React.memo((props) => {
  console.log(
    "Hey I'm only rendered the first time, check React.memo + callback"
  );

  return <button onClick={props.onReset}>Reset value</button>;
});

export const MyComponent = () => {
  const [username, setUsername] = React.useState("John");
  const [lastname, setLastname] = React.useState("Doe");

  const resetNameCallback = () => {
    setUsername("");
  };

  return (
    <>
      <h3>
        {username} {lastname}
      </h3>
      <input value={username} onChange={(e) => setUsername(e.target.value)} />
      <input value={lastname} onChange={(e) => setLastname(e.target.value)} />
      <ResetValue onReset={resetNameCallback} />
    </>
  );
};

¿Qué tenemos aquí?

  • Un componente padre que muestra nombre y apellidos y ofrece un botón para resetear el nombre que está encapsulado en un componente.

  • El componente de Reset optimizado con React memo (se llama ResetValue), y se supone que solo se renderiza la primera vez.

  • Peeroo... ojo el estamos pasando una función como prop, que se crea en cada renderizado de MyComponent.

Si probamos verás que cada vez que cambiamos alguno de los valores de los inputs, se renderiza el componente ResetValue y se imprime en consola el mensaje.

¿Cómo solucionabamos esto antes que no teníamos el compilador de React, con useCallback?

Vamos a probarlo.

./src/demo.tsx

export const MyComponent = () => {
  const [username, setUsername] = React.useState("John");
  const [lastname, setLastname] = React.useState("Doe");

-  const resetNameCallback = () => {
+  const resetNameCallback = React.useCallback(() => {
    setUsername("");
-  };
+  }, []);

  return (

Si ahora probamos, verás que el componente ResetValue ya no se renderiza cada vez que cambiamos el valor de los inputs.

Vamos a probar con el compilador de React, lo habilitamos de nuevo.

./vite.config.ts

./vite.config.ts

export default defineConfig({
  plugins: [
    react(),
-    /*{
+   {
      babel: {
        plugins: [["babel-plugin-react-compiler", { target: "19" }]],
      },
+    }
-    }*/
  ],
});

Y... redoble de tambores, vamos a quitar tanto el React.memo como el useCallback y ver si el compilador hace su trabajo.

./src/demo.tsx

- const ResetValue: React.FC<Props> = React.memo((props) => {
+ const ResetValue: React.FC<Props> = (props) => {
  console.log(
    "Hey I'm only rendered the first time, check React.memo + callback"
  );

  return <button onClick={props.onReset}>Reset value</button>;
- });
+ };
+  const resetNameCallback = () => {
-  const resetNameCallback = React.useCallback(() => {
    setUsername("");
+  };
-  }, []);

  return (

¡ Bingo! El componente ResetValue ya no se renderiza cada vez que cambiamos los valores de los inputs y no hemos tenido que añadir ningúna optimización manual.

¿Qué te parece si probamos con useMemo? En el siguiente ejemplo jugamos con useMemo

¿Funcionará? Veamos...

npm run dev