Pular para o conteúdo principal

useDLE() - [D]ata, [L]oading e [E]rror (dados, carregamento e erro)

Renderização de dados assíncronos de alto desempenho, sem overfetching. Com metadados do fetch.

Caso você não possa usar suspense, useDLE() é igual ao useSuspense(), mas retorna os valores [D]ata [L]oading [E]rror.

useDLE() reage às mutações de dados, renderizando novamente somente quando necessário.

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▶

Comportamento​

Status de expiraçãoFetchDataLoadingErrorCondições
Inválidosim1undefinedtruefalsenão está na store, exclusão, invalidação, invalidIfStale
Desatualizadosim1desnormalizadofalsefalse(primeira renderização, mudança de args) & expiração < agora
Válidonãodesnormalizadofalsetalvez2conclusão do fetch
nãoundefinedfalsefalsenull usado como segundo argumento
observação
  1. Fetches idênticos são automaticamente deduplicados
  2. Erros hard devem ser capturados por Error Boundaries
React Native

Ao usar o React Navigation, useDLE() dispara fetches ao receber foco se os dados forem considerados desatualizados.

Dependências condicionais

Usar null como segundo argumento de qualquer hook do Data Client significa "não fazer 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;
};

Exemplos​

Detalhe​

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 evita vincular e buscar os dados

▶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>;
}

Dados incorporados​

Quando as entidades são armazenadas em estruturas aninhadas, essa estrutura é mantida.

▶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>
  );
}

Reações do Github​

useDLE() nos permite buscar de forma declarativa as reações em qualquer página de issue no momento em que navegamos até ela. Isso nos permite não bloquear a exibição da página de issues caso as reações ainda não tenham terminado de carregar.

Normalmente é melhor envolver casos como este em novos Suspense Boundaries. No entanto, nossa biblioteca de componentes ant design não permite isso.

Explore o exemplo github-app

More Demos