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 />);
Comportamiento
| Caducidad | Fetch | Data | Loading | Error | Condiciones |
|---|---|---|---|---|---|
| Inválido | sí1 | undefined | true | false | no está en el store, eliminación, invalidación, invalidIfStale |
| Obsoleto | sí1 | desnormalizado | false | false | (primer render, cambio de args) & caducidad < ahora |
| Válido | no | desnormalizado | false | quizás2 | fetch completado |
| no | undefined | false | false | null usado como segundo argumento |
- Los fetches idénticos se deduplican automáticamente
- Errores graves que deben ser capturados por Error Boundaries
Al usar React Navigation, useDLE() activará fetches al enfocar la pantalla si los datos se consideran obsoletos.
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
- 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;
};
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 />);
Condicional
null evitará enlazar y obtener datos
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á.
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> ); }
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