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 />);
Comportamento
| Status de expiração | Fetch | Data | Loading | Error | Condições |
|---|---|---|---|---|---|
| Inválido | sim1 | undefined | true | false | não está na store, exclusão, invalidação, invalidIfStale |
| Desatualizado | sim1 | desnormalizado | false | false | (primeira renderização, mudança de args) & expiração < agora |
| Válido | não | desnormalizado | false | talvez2 | conclusão do fetch |
| não | undefined | false | false | null usado como segundo argumento |
- Fetches idênticos são automaticamente deduplicados
- Erros hard devem ser capturados por Error Boundaries
Ao usar o React Navigation, useDLE() dispara fetches ao receber foco se os dados forem considerados desatualizados.
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
- Type
- With Generics
function useDLE(
endpoint: ReadEndpoint,
...args: Parameters<typeof endpoint> | [null]
): {
data: Denormalize<typeof endpoint.schema>;
loading: boolean;
error: Error | undefined;
};
function useDLE<
E extends EndpointInterface<
FetchFunction,
Schema | undefined,
undefined
>,
Args extends readonly [...Parameters<E>] | readonly [null],
>(
endpoint: E,
...args: Args
): {
data: DenormalizeNullable<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 />);
Condicional
null evita vincular e buscar os dados
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.
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: '', }, });
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