Saltar al contenido principal

useDLE() - Estado con [D]ata [L]oading [E]rror

Renderizado de datos asíncronos de alto rendimiento sin sobrecargar las solicitudes. Con metadatos del fetch.

Si no puedes usar suspense, useDLE() es igual que useSuspense(), pero devuelve los valores [D]ata [L]oading [E]rror.

useDLE() reacciona a las mutaciones de datos; vuelve a renderizar solo cuando es necesario.

Uso​

import React from 'react';
import { useDLE } from '@data-client/react';
import { ProfileResource } from './ProfileResource';

function ProfileList(): React.JSX.Element {
  const { data, loading, error } = useDLE(ProfileResource.getList);
  if (error) return <div>Error {`${error.status}`}</div>;
  if (loading || !data) return <Loading />;
  return (
    <div>
      {data.map(profile => (
        <div className="listItem" key={profile.pk()}>
          <Avatar src={profile.avatar} />
          <div>
            <h4>{profile.fullName}</h4>
            <p>{profile.bio}</p>
          </div>
        </div>
      ))}
    </div>
  );
}
render(<ProfileList />);
Resultado
Store▶

Comportamiento​

CaducidadFetchDataLoadingErrorCondiciones
Inválidosí1undefinedtruefalseno está en el store, eliminación, invalidación, invalidIfStale
Obsoletosí1desnormalizadofalsefalse(primer render, cambio de args) & caducidad < ahora
Válidonodesnormalizadofalsequizás2fetch completado
noundefinedfalsefalsenull usado como segundo argumento
nota
  1. Los fetches idénticos se deduplican automáticamente
  2. Errores graves que deben ser capturados por Error Boundaries
React Native

Al usar React Navigation, useDLE() activará fetches al enfocar la pantalla si los datos se consideran obsoletos.

Dependencias condicionales

Usar null como segundo argumento de cualquier hook de Data Client significa "no hacer nada".

// todo could be undefined if id is undefined
const todo = useDLE(TodoResource.get, id ? { id } : null);

Tipos​

function useDLE(
endpoint: ReadEndpoint,
...args: Parameters<typeof endpoint> | [null]
): {
data: Denormalize<typeof endpoint.schema>;
loading: boolean;
error: Error | undefined;
};

Ejemplos​

Detalle​

import React from 'react';
import { useDLE } from '@data-client/react';
import { ProfileResource } from './ProfileResource';

function ProfileDetail(): React.JSX.Element {
  const {
    data: profile,
    loading,
    error,
  } = useDLE(ProfileResource.get, { id: 1 });
  if (error) return <div>Error {`${error.status}`}</div>;
  if (loading || !profile) return <Loading />;
  return (
    <div className="listItem">
      <Avatar src={profile.avatar} />
      <div>
        <h4>{profile.fullName}</h4>
        <p>{profile.bio}</p>
      </div>
    </div>
  );
}
render(<ProfileDetail />);
Resultado
Store▶

Condicional​

null evitará enlazar y obtener datos

▶Resources
▶PostWithAuthor
import { useDLE } from '@data-client/react';
import { PostResource, UserResource } from './Resources';

export default function PostWithAuthor({ id }: { id: string }) {
  const postDLE = useDLE(PostResource.get, { id });
  if (postDLE.error) return <div>Error {`${postDLE.error.status}`}</div>;
  if (postDLE.loading || !postDLE.data) return <Loading />;
  const authorDLE = useDLE(
    UserResource.get,
    postDLE.data.userId
      ? {
          id: postDLE.data.userId,
        }
      : null,
  );
  if (authorDLE.error)
    return <div>Error {`${authorDLE.error.status}`}</div>;
  if (authorDLE.loading || !authorDLE.data) return <Loading />;

  return <div>{authorDLE.data.username}</div>;
}

Datos incrustados​

Cuando las entities se almacenan en estructuras anidadas, esa estructura se conservará.

▶api/Post
import { Entity, RestEndpoint, Collection } from '@data-client/rest';

export class PaginatedPost extends Entity {
  id = '';
  title = '';
  content = '';

  static key = 'PaginatedPost';
}

export const getPosts = new RestEndpoint({
  path: '/post',
  searchParams: { page: '' },
  schema: {
    results: new Collection([PaginatedPost]),
    nextPage: '',
    lastPage: '',
  },
});
▶ArticleList
import { useDLE } from '@data-client/react';
import { getPosts } from './api/Post';

export default function ArticleList({ page }: { page: string }) {
  const { data, loading, error } = useDLE(getPosts, { page });
  if (error) return <div>Error {`${error.status}`}</div>;
  if (loading || !data) return <Loading />;
  const { results: posts, nextPage, lastPage } = data;
  return (
    <div>
      {posts.map(post => (
        <div key={post.pk()}>{post.title}</div>
      ))}
    </div>
  );
}

Reacciones de Github​

useDLE() nos permite obtener de forma declarativa las reacciones de cualquier página de issue en el momento en que navegamos a ella. Esto nos permite no bloquear la visualización de la página del issue si las reacciones aún no terminaron de cargarse.

Normalmente es mejor envolver casos como este en nuevos Suspense Boundaries. Sin embargo, nuestra biblioteca de componentes ant design no lo permite.

Explora el ejemplo github-app

More Demos