hand Inicio
hand JSBloqs
hand GutenBloqs
Qu茅?
noched铆a

DESARROLLO WEB con
REACT y WORDPRESS

Ap煤ntate a la newsletter (escribo algo de tanto en cuanto)

Crear un scroll infinito con React y un custom hook

400 palabras
2 minutos
September 24, 2020
blogjavascript

Se trata de cargar nuevos elementos en respuesta a un evento, y la manera m谩s c贸moda de hacerlo es mediante un hook

Cargar datos a medida que el usuario lo pide, bien apretando un bot贸n o bien cuando ocurra un evento de scroll es una manera excelente de evitar sobrecargar nuestro JS Bundle y el n煤mero de nodos DOM a procesar, algo que siempre tiene un impacto alto en los score de Lighthouse (y todo lo que ello implica para el posicionamiento web)

Por lo tanto, si nuestro caso aplica (no hay nada peor que optimizar cuando no es necesario), implementar un infinite scroll es el camino a seguir

Opciones varias

Tenemos muchas opciones para implementar esto

La posiblemente mejor (por aquello de no reinventar la rueda y utilizar soluciones muy probadas y s贸lidas): utilizar librer铆as externas

Por ejemplo

Pero si no nos apetece, siempre podemos hacerlo nosotros mismos

Utilizando un hook

Un hook no es m谩s que una manera de estructurar una funci贸n que nos facilita su encapsulamiento y su reutilizaci贸n (en un contexto de React)

El hook es el envoltorio, pero de qu茅 ir谩 el contenido?

Un infinite scrolling se refiere simplemente al hecho de cargar elementos en la medida en que los necesitemos, ya sea porque el usuario se est谩 acercando al 煤ltimo elemento visible, o porque se aprieta un bot贸n de "m谩s entradas"

Para usos extremos no s贸lo necesitar铆amos ir a帽adiendo esos nuevos elementos sino que tambi茅n ser铆a cr铆tico ir eliminando los elementos primeros (que ya est谩n fuera de la visi贸n del usuario), para evitar sobrecargar el DOM y que la p谩gina se vaya volviendo m谩s y m谩s pesada

Pero si nuestro contenedor no espera miles de elementos esta optimizaci贸n es innecesaria

En este caso, pediremos una nueva imagen de picsum.photos, haremos bloques de 10 y al final un bot贸n para pedir otro bloque de 10, y as铆 succesivamente

Estos bloques podr铆an ser art铆culos, temas, herramientas, y podr铆amos ya tener un n煤mero total de elementos

Una implementaci贸n simple ser铆a la siguiente, sin hook

jsx
import React, { useState, useEffect } from 'react'
export default function App() {
const [images, setImages] = useState([])
const [blocks, setBlocks] = useState(1)
const more = async () => {
const more_images = await fetch_images(blocks + 1)
setBlocks(prev => prev + 1)
setImages(prev => [...prev, ...more_images])
}
const fetch_images = async page => (await fetch(`https://picsum.photos/v2/list?page=${page}&limit=10`)).json()
useEffect(() => {
;(async () => {
const picsum = await fetch_images(0)
setImages(picsum)
})()
}, [])
return (
<div className="App">
<div style={{ display: 'flex', flexDirection: 'column' }}>
{images.map((el, i) => (
<img
key={`img${i}`}
src={el.download_url}
style={{
width: '150px',
height: 'auto',
marginBottom: '10px',
borderRadius: '3px',
}}
alt=""
/>
))}
</div>
<button style={{ marginBottom: '100px' }} onClick={more}>
more images
</button>
</div>
)
}
Ver en CodeSandBox

Aqu铆 cada vez que apretamos el bot贸n pedimos nuevas im谩genes a picsum y se las a帽adimos al array, guardado en el state images, y listos

Si en lugar de apretar un bot贸n queremos que sea autom谩tico al pasar por un elemento determinado (por ejemplo el pen煤ltimo del array), yo lo har铆a con la librer铆a react-intersection-observer

Pero sin entrar en esto, la gracia ahora es convertir el c贸digo de antes en un hook

Qu茅 problema nos solucionar铆a un hook?

B谩sicamente simplificar el c贸digo, encapsularlo y sacarlo de aqu铆, porque si queremos utilizar la misma l贸gica en otro componente tendremos que replicar todas las funciones y contaminar ese c贸digo, algo que nunca ser谩 buena idea

Con el hook lo que queremos es una funci贸n que nos devuelva lo que necesitemos, y listos, y en este caso lo suyo ser铆a que nos devolviese el array de im谩genes, y la funci贸n more()

jsx
import React, { useState, useEffect } from 'react'
export default function App() {
const [images, more] = useInfinitePicsum()
return (
<div className="App">
<div style={{ display: 'flex', flexDirection: 'column' }}>
{images.map((el, i) => (
<img
key={`img${i}`}
src={el.download_url}
style={{
width: '150px',
height: 'auto',
marginBottom: '10px',
borderRadius: '3px',
}}
alt=""
/>
))}
</div>
<button style={{ marginBottom: '100px' }} onClick={more}>
more images
</button>
</div>
)
}
const useInfinitePicsum = () => {
// estado para almacenar las im谩genes
const [images, setImages] = useState([])
// estado para contar el n煤mero de bloques que pido, lo necesito para que picsum no me devuelva siempre las mismas im谩genes
const [blocks, setBlocks] = useState(1)
// funci贸n para pedir m谩s im谩genes
const more = async () => {
const more_images = await fetch_images(blocks + 1)
setBlocks(prev => prev + 1)
setImages(prev => [...prev, ...more_images])
}
// funci贸n para pedir (esta vez literalmente) las imagenes a picsum
const fetch_images = async page => (await fetch(`https://picsum.photos/v2/list?page=${page}&limit=10`)).json()
// useEffect para ejecutar al principio la primera "pedida" de im谩genes
useEffect(() => {
;(async () => {
const picsum = await fetch_images(0)
setImages(picsum)
})()
}, [])
return [images, more]
}
Ver en CodeSandBox

Con esto la l贸gica React de la funci贸n principal es muy f谩cil de entender, y la l贸gica del hook es la que encapsula todo lo que viene a ser el crear el infinite scroll

Listos!

馃檵鈥嶁檪锔

Qu茅 tal la entrada?

馃憣 Bien 馃檶馃檶
馃憤 Bien, pero algunas cosas podr铆an explicarse mejor 馃槵
馃し鈥嶁檪锔 Da por sentadas demasiadas cosas 馃槖
馃し鈥嶁檪锔 A ver, hay poca chicha 馃槵
馃し鈥嶁檪锔 Los ejemplos no son muy claros 馃檱鈥嶁檪锔
馃し鈥嶁檪锔 No se entiende, est谩 mal escrito 馃憥
鉁嶏笍 Hay errores, rev铆salo en cuanto puedas 馃檹
Enviar Feedback 鉁嶏笍
El texto est谩 en blanco!
Gracias por enviarme tu opini贸n
馃憤

Si quieres explorar m谩s cursos y m谩s entradas en el blog, los tienes todos en la p谩gina principal, y si el contenido te ha ayudado dame las gracias por ejemplo por twitter con este enlace 馃憤

Privacidad
by kuworking.com
[ 2020 >> kuworking ]