Saltar al contenido principal

Data Client

Mutaciones reactivas

Renderiza datos con useSuspense(). Luego muta con Controller.fetch().

Esto actualiza todos los usos de forma atómica e inmediata sin peticiones adicionales. Reactive Data Client garantiza automáticamente la consistencia e integridad global de los datos, incluso con las condiciones de carrera más difíciles.

Editor en vivo
import { UserResource } from './resources';

export default function ProfileEdit({ id }: { id: number }) {
  const user = useSuspense(UserResource.get, { id });

  const controller = useController();
  const handleChange = ({ currentTarget: { value: name } }) =>
    controller.fetch(UserResource.partialUpdate, { id }, { name });

  return (
    <TextInput
      label="Name"
      value={user.name}
      onChange={handleChange}
    />
  );
}
Resultado
Store▶
Editor en vivo
import { UserResource } from './resources';

export default function ProfileEdit({ id }: { id: number }) {
  const { user } = useSuspense(UserResource.get, { id });

  const controller = useController();
  const handleChange = ({ currentTarget: { value: name } }) =>
    controller.fetch(UserResource.update, { id, name });

  return (
    <TextInput
      label="Name"
      value={user.name}
      onChange={handleChange}
    />
  );
}
Resultado
Store▶

Datos estructurados

La consistencia de datos, el rendimiento y la seguridad de tipos escalan aunque tus datos se vuelvan más complejos.

Las creaciones y eliminaciones actualizan de forma reactiva las listas correctas, incluso cuando esas listas están anidadas dentro de otros objetos.

Modela incluso los datos más complejos con soporte polimórfico y para objetos y mapas sin límites.

Editor en vivo
import { TodoResource } from './resources';

export default function NewTodo({ userId }: { userId: number }) {
  const controller = useController();
  const handleKeyDown = async e => {
    if (e.key === 'Enter') {
      controller.fetch(TodoResource.getList.push, {
        userId,
        title: e.currentTarget.value,
      });
      e.currentTarget.value = '';
    }
  };
  return (
    <div className="listItem nogap">
      <label>
        <input type="checkbox" name="new" checked={false} disabled />
        <TextInput size="small" onKeyDown={handleKeyDown} />
      </label>
      <CancelButton />
    </div>
  );
}
Resultado
Store▶

Actualizaciones en vivo

Mantén los cambios remotos sincronizados con useLive().

Polling, SSE y Websocket o soporte para un protocolo propio con middlewares

Editor en vivo
import { getTicker } from './resources';

export default function AssetPrice({ symbol }: { symbol: string }) {
  const productId = `${symbol}-USD`;
  const ticker = useLive(getTicker, { productId });
  return (
    <tr>
      <th>{symbol}</th>
      <td align="right">
        <NumberFlow
          value={ticker.price}
          format={{ style: 'currency', currency: 'USD' }}
        />
      </td>
    </tr>
  );
}
Resultado
Store▶

Integridad de datos

Tipos inferidos sólidos; una única fuente de verdad, referencialmente estable, garantiza la consistencia; las invariantes asíncronas facilitan evitar condiciones de carrera

Rendimiento

Navegación 24x más rápida que React sin librerías, 10x más rápida que TanStack Query y SWR. Mutaciones 92x más rápidas que TanStack Query, SWR y React sin librerías.

Composición sobre configuración

Declara lo que necesitas donde lo necesitas. Comparte definiciones de datos entre plataformas, componentes, protocolos y comportamientos.

Adopción incremental

Empieza rápido con una definición de datos de una línea y un enlace de datos de una línea. Luego añade TypeScript, caché normalizada con Schemas, actualizaciones optimistas y más.

Una aplicación completa

Un explorador de issues y pull requests de GitHub sobre la API de GitHub en vivo, creado con resources REST y Suspense.

Explora el ejemplo github-app

More Demos