restate / v1.0.0

Suscríbete solo a lo que necesitas

Elige de qué parte de un store depende cada componente, compara objetos con shallow, agrupa cambios con batch y conecta eventos externos.

En esta páginaPasa un selectorPruébaloSelecciona varios campos con shallowEscribe tu propia comparaciónAgrupa cambios con batchSuscríbete fuera de ReactConecta eventos externos

Pasa un selector

Llama al hook con una función que elige lo que el componente necesita. Tras cada cambio, restate ejecuta el selector y compara el resultado con el anterior usando Object.is. Si son iguales, el componente no se renderiza.

La nota cambia. ¿Se renderiza ItemCount?

No. Su selector sigue devolviendo el mismo número de artículos, así que la selección es igual y no se le pide a React que lo renderice.

JavaScript / JSX
const useCart = restate({ items: ['Book'], coupon: '', note: '' });

function ItemCount() {
  // Re-renders only when the number of items changes.
  const count = useCart((cart) => cart.items.length);
  return <p>{count} items</p>;
}

Pruébalo

Cambia campos y mira los contadores de renders. Desactiva shallow para ver un selector que devuelve un objeto nuevo cada vez.

Preparando el ejemplo…

Selecciona varios campos con shallow

Un selector que construye un objeto devuelve uno nuevo cada vez, así que Object.is siempre ve un cambio. Pasa shallow como segundo argumento: compara los campos propios del objeto a un nivel de profundidad.

shallow también compara las entradas de arrays, Map y Set a un nivel de profundidad.

JavaScript / JSX
import { restate, shallow } from '@kkwaenggwari/restate';

function CartSummary() {
  const { count, coupon } = useCart(
    (cart) => ({ count: cart.items.length, coupon: cart.coupon }),
    shallow,
  );
  return (
    <p>
      {count} items · {coupon || 'no coupon'}
    </p>
  );
}

Escribe tu propia comparación

Cualquier función (left, right) => boolean sirve como segundo argumento. Úsala cuando shallow no sea suficiente, por ejemplo para comparar una lista por ids.

JavaScript / JSX
const ids = useCart(
  (cart) => cart.items.map((item) => item.id),
  (left, right) => left.length === right.length && left.every((id, index) => id === right[index]),
);

Agrupa cambios con batch

Cada set notifica a los suscriptores de inmediato. Cuando una acción cambia varios stores, envuélvela en batch: la memoria se actualiza al momento y los suscriptores se ejecutan una vez tras el callback.

JavaScript / JSX
import { batch } from '@kkwaenggwari/restate';

function checkout() {
  batch(() => {
    useCart.set((cart) => ({ ...cart, items: [] }));
    useOrder.set((order) => ({ ...order, status: 'paid' }));
  });
  // Subscribers run once, after both stores changed.
}

Suscríbete fuera de React

subscribeSelector te llama solo cuando cambia el valor seleccionado, con la misma función de comparación opcional.

JavaScript / JSX
const stop = useCart.subscribeSelector(
  (cart) => cart.items.length,
  (count, previous) => analytics.track('cart-size', { count, previous }),
);

Conecta eventos externos

El segundo argumento de restate puede ser un updater. Arranca cuando el primer componente o suscriptor empieza a escuchar y su limpieza se ejecuta cuando el último deja de hacerlo, así que los eventos del navegador, los sockets o los sensores solo están conectados mientras hacen falta.

Usa start() y stop() para controlarlo a mano.

JavaScript / JSX
import { restate } from '@kkwaenggwari/restate';

// Listens while at least one component or subscriber uses the store.
export const useOnline = restate(true, ({ setState }) => {
  const update = () => setState(navigator.onLine);
  window.addEventListener('online', update);
  window.addEventListener('offline', update);
  update();
  return () => {
    window.removeEventListener('online', update);
    window.removeEventListener('offline', update);
  };
});

Buscar en la documentación

Busca en títulos, descripciones y texto de todas las guías.