Saltar al contenido

Jerarquía de componentes y cómo obtener datos de sincronización

Ahora que sabemos cómo obtener datos asíncronos en React, veamos cómo podemos mostrar datos en el componente y algunas de las jerarquías de los componentes.

Componente único

En una jerarquía de un solo componente, los datos se obtienen y se presentan en el mismo componente. Los componentes pueden obtener datos con un solo clic una vez que se montan usando el método de ciclo de vida componentDidMount(), o periódicamente para mantenerlos sincronizados con el servidor.

Jerarquía de componentes y cómo obtener datos de sincronización
Jerarquía de componentes y cómo obtener datos de sincronización

Echemos un vistazo a cómo podemos obtener datos usando el método componentDidMount().

12345678910111213141516171819202122232425classPostsextendsComponent{ state ={ posts:[]};asynccomponentDidMount(){const posts =awaitgetPosts();this.setState({ posts });}render(){return(<divclass=$0027posts-container$0027;{this.state. posts.map(post===;(<divclass={`post post-id-${post.id}};};divclass=$0027post-imagen$0027};}imgsrc={post. imageUrl};*div;*;*divclass=$0027post-title$0027*;*h4;*{post.title}<*h4;*;*div;*;*div;*;*div; ))};*div) }}

jsx

Como getPosts() es una función de asincronía, devolverá una promesa, así que he usado la sintaxis de asincronía-esperanza. En la siguiente línea, he actualizado el estado para mantener los puestos. En el método render(), he usado el método Array.map() para mostrar cada mensaje.

Ahora, hagamos lo mismo usando la última API de React Hooks. Los React Hooks permiten el uso para tener un estado dentro de un componente funcional.

1234567importReact,{ useState }from "react";constPosts=()= &gtconst[posts, setPosts]=useState([]);// return};

jsx

El método useState() declara una variable de estado y un método que puede ser usado para cambiar la variable de estado. Pasamos en el estado inicial al método useState(), en nuestro caso, una matriz vacía. Devuelve una matriz compuesta por dos valores: el estado inicial y el método que la modifica. En nuestro ejemplo, los valores se almacenan en posts y setPosts, respectivamente.

Para realizar una búsqueda de datos asíncrona, usamos la función de gancho useEffect.

1234567891011121314151617181920212223242526272829importReact,{ useState, useEffect }from "react";constPosts=()= &gt {const[posts, setPosts]=useState([]); useEffect(()=[(async()=[;{const fetchedPosts =awaitgetPosts();setPosts(fetchedPosts);})();},[]);return(<divclass=$0027posts-container$0027{posts. map(post={N-;(<divclass={`post post-id-${post.id}};};divclass=$0027post-imagen$0027};}imgsrc={post. imageUrl};³³³$0027divclass=$0027post-title$0027³³³$0027h4;³³³$0027{post.title}</h4;³³³$0027³³³$0027div³³³$0027³³³$0027³³³$0027post$0027$0027; ))} ³³$0027divclass=$0027post-title$0027³³³$0027³³³$0027³³³$0027³³$0027$0027³³³$0027³³$0027$0027³³$0027$0027³³$0027$0027.
jsx

La función useEffect() toma una función como primer argumento, y el segundo argumento es una matriz de todas las variables de las que depende la función. En nuestro caso, es importante pasar un array vacío al gancho; de lo contrario, la función se ejecutará cada vez que el componente se actualice. Este es un error desagradable, y deberíamos evitarlo. Habréis notado que he envuelto el bloque de asincronía en una función autoinvocable. Eso es porque la función useEffect no debe devolver un objeto de la Promesa, y arrojará un error si lo intenta.

Componente de orden superior (HOC)

En una jerarquía de componentes de orden superior, los datos se recogen en el componente padre y se transmiten como accesorios a un componente hijo. Otros componentes anidados en el componente hijo pueden recibir diferentes partes de los datos obtenidos.

La idea es separar la lógica de la obtención de datos de la vista y centrarse más en el manejo o la presentación de los datos al usuario. Aquí se hace más hincapié en el SOC, o separación de preocupaciones.

Así que en nuestro componente padre, tendremos el siguiente código.

123456789101112131415161718constPosts=()=[[const[posts, setPosts]=useState([]);useEffect((()=[(async()=[;{const fetchedPosts =awaitgetPosts();setPosts(fetchedPosts);})();},[]);return(<div>{this. state.posts.map(post={post={post}/{;))}</div>);};

jsx

Y en nuestro componente infantil escribiremos la plantilla para mostrar el post:

12345678910constPost={post}={post};(<divclass={`post post-id-${post.id}};<divclass=$0027post-imagen$0027={post.
jsx

Como pueden ver, el componente principal es ahora más ligero y más legible en comparación con la jerarquía de componente único. De esta manera, podemos separar los componentes de presentación del componente contenedor. Los componentes de presentación están más orientados a generar el marcado para la salida de los datos, mientras que los componentes contenedores se encargan de buscar y manejar los datos de la API del backend.

Componente de Render Props

En una jerarquía de componentes de hélices de render, un componente toma una función que devuelve un elemento React como hélice y lo llama en su función de render() en lugar de implementar su lógica de render.

Considere este ejemplo. Digamos que, junto con los mensajes, también tienes un componente que muestra los datos del usuario. En ese caso, querrías encapsular y reutilizar el código entre los dos componentes. Para ello, crearemos una que tomará la URL como un accesorio junto con una función de renderizado.

12345// para mostrar los puestos<FetchComponentrender={post={post={post}/// para mostrar los usuarios<FetchComponentrender={user=======usuario
jsx

Ahora, escribamos el .

12345678910111213141516constFetchComponent=props=;{const[data, setData]=setState([]);useEffect((()=. get(props.url);setData(response.data);})();},[]);return(<div>{data.map(dataItem=> props.render(dataItem))}</div>);};

jsx

¿No sería bueno mostrar un indicador de carga? Hagámoslo.

1234567891011121314151617181920constFetchComponent=props=;{const[data, setData]=setState([]);const[isLoading, setLoading]=setState(false);useEffect((()=(async()=(setLoading(true);const response =wait axios. get(props.url);setLoading(false);setData(response.data);})();},[]);if(isLoading)return<Loader> return ( <div>{data.map(dataItem=§; props.render(dataItem))}</div> );};

jsx

La jerarquía de componentes de utilería puede ser usada para crear componentes reutilizables y poderosos, ocultando la complejidad y así ayudar a escribir código legible y mantenible.

Podemos hacer nuestro aún más organizado y mantenible encapsulando la lógica de búsqueda en un gancho React personalizado.

Vamos a crear un gancho UseFetch.

useFetch.js

1234567891011121314151617importReact,{useState, useEffect }from "react";exportfunctionuseFetch(url){const[data, setData]=setState([]); const[isLoading, setLoading]=setState(false);useEffect(()= &gt(async()= >{setLoading(true);const response =await axios. get(props.url);setLoading(false);setData(response.data);})();},[]);return[data, isLoading];}

jsx

En nuestra podemos recortar el código y en su lugar usar nuestra función de gancho personalizado.

FetchComponent.js

123456789101112import{useFetch}from$0027./useFetch.js$0027;constFetchComponent=props={const[data, isLoading]=useFetch(props. url);if(isLoading)return<Loader> return ( <div>{data.map(dataItem= > props.render(dataItem))}</div> );};

jsx