Les dejo un artículo que escribí sobre el hook useEffect por si les puede ayudar a complementar esta clase: https://midu.dev/react-hooks-use-effect-funcionalidad-en-el-ciclo-vida-componentes/
Introducción al curso avanzado de React
Qué necesitas para este curso y qué aprenderás sobre React.js
Proyecto y tecnologías que usaremos
Preparando el entorno de desarrollo
Clonando el repositorio e instalando Webpack
Instalación de React y Babel
Zeit es ahora Vercel
Linter, extensiones y deploy con Now
Creando la interfaz con styled-components
¿Qué es CSS-in-JS?
Creando nuestro primer componente: Category
Creando ListOfCategories y estilos globales
Usar información real de las categorías
Creando PhotoCard y usando react-icon
SVGR: de SVG a componente de ReactJS
Creando animaciones con keyframes
Hooks
¿Qué son los Hooks?
useEffect: limpiando eventos
useCategoriesData
Usando Intersection Observer
Uso de polyfill de Intersection Observer e imports dinámicos
Usando el localStorage para guardar los likes
Custom Hooks: useNearScreen y useLocalStorage
GraphQL y React Apollo
¿Qué es GraphQL y React Apollo? Inicializando React Apollo Client y primer HoC
Parámetros para un query con GraphQL
Usar render Props para recuperar una foto
Refactorizando y usando variables de loading y error
Usando las mutaciones con los likes
Reach Router
¿Qué es Reach Router? Creando la ruta Home
Usando Link para evitar recargar la página
Creando la página Detail
Agregando un NavBar a nuestra app
Estilando las páginas activas
Rutas protegidas
Gestión del usuario
Introducción a React.Context
Creación del componente UserForm; y Hook useInputValue
Estilando el formulario
Mutaciones para registro
Controlar estado de carga y error al registrar un usuario
Mutaciones para iniciar sesión
Persistiendo datos en Session Storage
Hacer like como usuario registrado
Mostrar favoritos y solucionar fetch policy
Cerrar sesión
Mejores prácticas, SEO y recomendaciones
Últimos retoques a las rutas de nuestra aplicación
React Helmet
Midiendo el performance de nuestra app y usando React.memo()
React.lazy() y componente Suspense
Usando PropTypes para validar las props
PWA: generando el manifest
PWA: soporte offline
Testing con Cypress
Conclusiones
¡Felicidades!
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Aportes 73
Preguntas 12
Les dejo un artículo que escribí sobre el hook useEffect por si les puede ayudar a complementar esta clase: https://midu.dev/react-hooks-use-effect-funcionalidad-en-el-ciclo-vida-componentes/
Yo en vez de hacer un fadeIn hice que se mostrara desde arriba. También aproveché la animación para no renderear el componente cada vez que el estadoshowFixed
cambie si no que la animación se encargue de sacarlo del viewport.
Usando react spring 😛
un pequeño shortcode para usar los Fragments de react es usar " <>" y “</>” para cerrar. No hace falta importar {Fragment} de react, ya que ya lo interpreta.
<>
{renderList()}
{renderList(true)}
</>
Les dejo esta animación de efecto rebote
const bounceDownKeyFrames = keyframes`
0% {
top: -70px;
}
25% {
top: 0px;
}
40%{
top: 10px
}
65%{
top: -3px
}
100% {
top: 0px;
}
`
export const bounceDown = ({ time = '1s', type = 'ease' } = {}) =>
css`
animation: ${time} ${bounceDownKeyFrames} ${type};
`
Solo agregue la funcion de fadeIn en styles de la lista, para cuando es fixed:
import styled from 'styled-components'
import { fadeIn } from '../../styles/animation'
export const List = styled.ul`
display: flex;
overflow: scroll;
width: 100%;
&.fixed {
${fadeIn()};
background-color: #fff;
border-radius: 60px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
left: 0;
margin: 0 auto;
max-width: 400px;
padding: 5px;
position: fixed;
right: 0;
top: -20px;
transform: scale(.5);
z-index: 1;
}
`
export const Item = styled.li`
padding: 0 8px;
`
Lista fija de categorías con la animación fadeIn que habíamos hecho:
hasta ahora pensaba que solo podía usar usar useEfect una sola vez en un componente 🤯🤯🤯
Con algunos comentarios de como entendí:
import React, { Fragment, useEffect, useState } from "react";
import { Category } from "../Category/Category";
import { List, Item } from "./styles";
export const ListOfCategories = () => {
/* setear el estado inicial */
const [categories, setCategories] = useState([]);
const [showFixed, setShowFixed] = useState(false);
/* useEffect se ejecuta cada vez que se renderiza el componente */
/* useEffect para obtener los datos del API */
useEffect(function () {
window
.fetch("http://localhost:3000/categories")
.then((res) => res.json())
.then((response) => {
setCategories(response);
});
}, []);
/* useEffect para mostrar las categorias cuando el scroll baje */
useEffect(function () {
/* Función onScroll para verificar el movimiento del scroll */
const onScroll = e => {
/* si el scroll es en Y es mayor a 200 entones newShowFixed == true */
const newShowFixed = window.scrollY > 200
/* si el */
showFixed !== newShowFixed && setShowFixed(newShowFixed)
}
/* Escuchar el movimiento del scroll, se suscribe un evento. */
document.addEventListener('scroll', onScroll)
console.log(showFixed);
/* cuando se desmonta el componente se elimina la suscripción al evento */
return () => document.removeEventListener('scroll', onScroll)
}, [showFixed])
const renderList = (fixed) => (
<List className={fixed ? 'fixed' : ''}>
{categories.map((category) => (
<Item key={category.id}>
<Category {...category} />
</Item>
))}
</List>
)
return (
<Fragment>
{renderList()}
{showFixed && renderList(true)}
</Fragment>
);
};
Mi propuesta para hacer el efecto de las categorias con IntersectionObserver 🤗🤗🤗:
Yo use una animación para cambiar el scale, dejo el snippet por si alguien quiere probarlo.
const scaleDown = keyframes`
from {
transform: scale(1);
}
to {
transform: scale(0.5);
}
`;
const scale = ({time = "1s", type = "ease"} = {}) => css`animation: ${time} ${scaleDown} ${type}`;
const Ul = styled.ul`
display: flex;
overflow: scroll;
width: 100%;
${props => props.fixed && css`
background: #ffffff;
border-radius: 60px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
left: 0;
margin: 0 auto;
max-width: 500px;
padding: 5px;
position: fixed;
right: 0;
top: -20;
transform: scale(0.5);
${scale}
z-index: 1;
`}
`;
Excelente…
Acá mi animación:
const positionDownKeyFrames = keyframes`
0%{
margin-top:-100px;
}
100%{
margin-top:0;
}
`
export const positionDown = ({ time = '1s', type = 'ease' } = {}) =>
css`animation: ${time} ${positionDownKeyFrames} ${type}`
De esta manera hice el efecto (con una ternary):
useEffect(function () {
function onScroll (e) {
window.scrollY > 200
? setShowFixed(true)
: setShowFixed(false)
}
document.addEventListener('scroll', onScroll)
return function () {
document.removeEventListener('scroll', onScroll)
}
}, [showFixed])
una lectura para entender mas de useEffect
useEffect en el ciclo de vida de componentes
no se si a alguien mas le paso, pero si no les sale la renderList(fixed) coloquenla antes que la renderList()
<>
{renderList(true)}
{renderList()}
</>
hola !
la url ("https://petgram-server.midudev.now.sh/categories
") para obtner las cetegorias esta devolviendo un 502
Aqui esta mi animacion espero les guste
Para los que viene de los cursos de oscar 😛 tambien podiamos indicar los fragment de esta manera “corta” <> </>
return (
<>
{renderList()}
{showFixed && renderList(true)}
</>
)
¿Es necesario usar doble llamado a la función renderList? ¿No es suficiente con algo así?
renderList(showFixed)
me surge una duda
const renderList = () => { ... }
no termina creando una nueva función en cada render del componente? o es algo por lo que no debería de preocuparme?
Cada vez voy notando el poder de utilizar styled-components en nuestros proyectos, incluso lo podemos usar para condicionar nuestro estado, excelente herramienta. 🚀…
Increíble 😱, llevo varios proyectos incorporando reactHooksy nunca se me había pasada por la cabeza hacer más de un useState, me acostumbre a resalizar solo 1 componentDidMount, pero me doy cuenta que el useState combina los poderes del componentDidUpdateen el array que recibe como segunda parámetro, es increíble, ahora mis aplicaciones tendrán un mejor rendimiento. 😄
Puedes describir como hacer un correcta estructura de archivos y carpeta para un proyecto?
Implementación del efecto fadeIn en la lista de categorias
import styled from 'styled-components'
import { fadeIn } from '../../styles/animation'
const List = styled.ul`
display: flex;
overflow-x: auto;
width: 100%;
&.fixed {
${fadeIn({ time: '0.8s', type: 'ease-in-out' })}
background: #fff;
border-radius: 60px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
left: 0;
margin: 0 auto;
max-width: 400px;
padding: 5px;
position: fixed;
right: 0;
top: -20px;
transform: scale(0.5);
z-index: 1;
}
`
const Item = styled.li`
padding: 0 8px;
`
export { List, Item }
Usando react-top-loading-bar
Code:
animation.js
import styled, { css, keyframes } from "styled-components";
const scale = keyframes`
from {
transform: scale(1);
top: -100px;
border-radius: 2px;
}
to{
transform: scale(.66);
border-radius: 60px;
}
`
export const scaleDown = ({ time = "1s", type = "ease" } = {}) => css`
animation: ${time} ${scale} ${type};
`;
que gran curso! lastima que necesite actualizacion
Para el reto solo importamos en los styles:
import { fadeIn } from ‘…/…/styles/animation’
Luego agregamos: ${fadeIn()} cuando se haga el fixed.
&.fixed {
${fadeIn()}
.
.
.
}
Les dejo otra forma utilizando Logical Operators y un video de @Midudev explicando sobre el uso de ternarias: https://www.youtube.com/watch?v=YFES8Nm6uF4
<List className={fixed &&= 'fixed'}>
//Code
</List>
Acá hay otra forma de hacer el toggle de las categorías:
useEffect(function () {
const onScroll = e => {
window.scrollY > 200 ? setShowFixed(true) : setShowFixed(false)
}
document.addEventListener('scroll', onScroll)
}, [])
Yo hice la comprobacion de esta manera para no hacer otra funcion
useEffect(() => {
const handleScroll = () => {
if (window.scrollY > 200) {
setFixedCategory(true);
} else {
setFixedCategory(false);
}
};
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, [fixedCategory]);
return (
<List className={fixedCategory ? "fixed" : null}>
{categories?.map((category) => (
<li key={category.id}>
<Category {...category} />
</li>
))}
</List>
);
};
export { ListOfCategories };
Hola!, el código en la descripcion de la clase aparece minificado. Al menos el index.js de ListOfCategories
Hola aquí les dejo mi aporte:
No es malo estar agregando eventos en cada render de la app?
Asi me quedo a mi, el escrolleable era un objeto del dom y no el window
import React,{ useEffect, useState } from "react"
import styled from "styled-components"
import { Category } from "../Category"
import db from "../../backend/api/db.json"
/// if use trick declare object: const renderList =(fixed, {delay: delay}=0 )=>
const renderList =(fixed, delay=0 )=> { return ( <>
<List className={ fixed? 'fixed' : '' }>
{ db.categories.map(
cat=>
<Item key={cat.id}>
<Category {...cat} delay={delay}/>
</Item>
)
}
</List>
</>
)};
const ListOfCategories =()=>{ const [showFixed, setShowFixed ] = useState(false)
useEffect(()=> {
const cards = document.querySelector("#scrolleable");
const onScroll = (cards=this.cards, e) =>{
const newShowFixed = cards.scrollTop>100;
showFixed !== newShowFixed && setShowFixed(newShowFixed);
}; cards.addEventListener('scroll', ()=>onScroll(cards) );
return ()=> cards.removeEventListener('scroll', onScroll);
},[showFixed])
return (
<>
{renderList()}
{showFixed && renderList(true)}
{/* {showFixed && renderList(true, {delay=10} )} */} //!trick
</>
)
}; export { ListOfCategories, renderList };
export const List = styled.section`
display: flex;
position: relative;
z-index: 1;
overflow: auto;
width: 100%;
height: 130px;
::-webkit-scrollbar {
display: none;
}
&.fixed{
border-radius: 1000px;
box-shadow: 0 0 20px rgba(0,0,0,.40);
position: sticky;
top: -36px;
right: 0;
left: 0;
margin: 0 auto;
max-width: 400px;
padding: 5px;
transform: scale(.5);
z-index: 13;
backdrop-filter: blur(30px);
}
`
export const Item = styled.article`
padding: 0 8px;
`
ListOfCategories/index.js
import React, {useState, useEffect} from 'react';
import {List, Item} from './styles';
import { Category } from '../Category';
export const ListOfCategories = () => {
const [categories, setCategories] = useState([]);
const [showFixed, setShowFixed] = useState(false);
//Show Categories fetching the data
useEffect(function(){
window.fetch('https://petgram-server-alejandroverita-alejandroverita.vercel.app/categories')
.then(res => res.json())
.then(data => {
setCategories(data)
})
}, [])
//Show categories when scroll is higher 200px
useEffect(()=>{
const onScroll = e => {
const newShowFixed = window.scrollY > 200
showFixed !== newShowFixed && setShowFixed(newShowFixed)
}
document.addEventListener('scroll', onScroll)
//Avoid memoryLeak
return () => document.removeEventListener('scroll', onScroll)
}, [showFixed])
const renderList = (fixed) => (
<List className={fixed ? 'fixed' : ''}>
{
categories.map(category =>
<Item key = {category.id}>
<Category {...category} />
</Item>
)
}
</List>
)
return (
<>
{renderList()}
{showFixed && renderList(true)}
</>
)
}
ListOfCategories/styles.js
import styled from 'styled-components';
import {scale} from '../../Styles/animation';
export const List = styled.ul`
display: flex;
overflow: scroll;
width: 100%;
//desaparece el scroll sin perder la funcionalidad
&::-webkit-scrollbar {
display: none;
};
&.fixed {
background-color: white;
border-radius: 60px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
left: 0;
margin: 0 auto;
max-width: 400px;
padding: 5px;
position: fixed;
right: 0;
top: -20px;
transform: scale(0.5);
${scale({time:'0.3s'})}
z-index: 1;
}
`
export const Item = styled.li`
padding: 0 8px;
list-style: none;
`
animation.js
import {keyframes, css} from 'styled-components';
const fadeInKeyframes = keyframes `
from {
filter: blur(5px);
opacity: 0;
}
to {
filter: blur(0);
opacity: 1;
}
`;
export const fadeIn = ({time = '1s', type='ease'} = {}) => css`
animation: ${time} ${fadeInKeyframes} ${type};
`;
const scaleDown = keyframes`
from {
transform: scale(1);
}
to {
transform: scale(0.5);
}
`;
export const scale = ({time='1s', type='ease'} = {})=> css `
animation: ${time} ${scaleDown} ${type};
`;
Para un mayor entendimiento del código, aconsejo sacar la función onScroll del useEffect… porfas, si hacer esto está mal, háganmelo saber
const onScroll = (e) => {
const newShowFixed = window.scrollY > 200
compare with showFixed
showFixed !== newShowFixed && setShowFixed(newShowFixed)
newShowFixed before is declarated
console.log('adios:(')
}
useEffect(() => {
document.addEventListener('scroll', onScroll)
return () => {
console.log('hola:)')
document.removeEventListener('scroll', onScroll)
}
}, [showFixed])
Tenia problemas con ejecutar el listener y traer el valor de window.scrollY. No se ejecutaba ninguno de los dos. Leyendo me encontre con que en los estilos globales al id #app le estamos pasadano un height: 100vh. Una vez lo quité, me funciono correctamente la accion de lista de categorias. Alguien me puede explicar por que?
#app{
box-shadow: 0 0 10px rgba(0,0,0,.05);
overflow-x: hidden;
//height: 100vh; // si se le da esta propiedad, no se puede acceder a window.scrollY ni document.addEventListener('scroll'...
padding-bottom: 10px;
}
Genial
ni idea que existia transform: scale(.5); jajaj
Les comparto un proyecto que hice, consumiendo una API https://petlove-3sbf43kkw-montilva74.vercel.app/, no es perfecto pero me siento orgullosa de todo.
const onScroll = () => {
window.scrollY > 200 ? setShowFixed(true) : setShowFixed(false);
};
Muy interesante, muchas gracias!!
Lo que no entendí al principio era el llamado a Vercel, pero ya en materia sólo tenía que llamar a la api:
Excelente, cosas que antes pensaba que eran tediosas de hacer en React ahora son simples.
Al crear la lista estática esta se muestra debajo de la lista fhtoCard, ¿como puedo solucionarlo?
Lista de categorias con el efecto fadeIn
https://ibb.co/3Mcb1d6
http://platzi.com/comentario/660554/
Al darle scroll para mostrar la lista estatica en mi proyecto esta se muestra por debajo de la lista fhotocard
@midudev como puedo usar variables de elementos dentro de otro elemento? Te hago un ejemplo:
Para estilos de categorias
export const Anchor = styled.a`
display: flex;
flex-direction: column;
text-align: center;
text-decoration: none;
width: 75px;
&.fixed {
width: 45px;
}
`
export const Image = styled.img`
border: 1px solid #ddd;
box-shadow: 0px 1px 14px rgba(0, 0, 0, .2);
border-radius: 50%;
height: auto;
overflow: hidden;
object-fit: cover;
height: 75px;
width: 75px;
`
Y teniendo otro elemento que sea el contenedor de los otros dos, por ejemplo
export const CategoryContainer = styled.div`
&.fixed {
a {
width: 45px;
}
img {
width: 45px;
height: 45px;
}
}
`
¿Cómo puedo hacer para que en vez de utilizar a, img, utilizar las constantes asociadas a ese elemento? Es decir:
export const CategoryContainer = styled.div`
&.fixed {
Anchor {
width: 45px;
}
Image {
width: 45px;
height: 45px;
}
}
`
¿Como puedo lograr algo similar?
Saludos Miguel, muy buen curso!.
Tengo una consulta: tengo un custom Hook llamado useFetch() que quiero usar como helper para todas las peticiones que necesite el sitio, el problema surge cuando lo quiero utilizar dentro de un useEffect, bien sea para una carga inicial o un pulling con interval, entiendo que es por las reglas de los Hooks.
La duda es, no es un caso correcto de use Hooks? es decir, debo reescribirlo como una funcion helper o estoy haciendo algo mal?
Muchas gracias.!
¡Geniaaal! Maravilloso efecto y super simple!
Solo tengo una duda y quizá sea ridícula, pero aún así no me privaré de expresarla @midudev ¿No hay problemas de performance al agregar el listener cada que se renderiza el componente? ¿O el browser se da cuenta que el listener en realidad no hay cambiado y lo gestiona?
Pero enserio me pareció brutal lo que hiciste por que mi solución hubiese sido mucho más compleja, ¡vivan los hooks!
Una pregunta, al desmontar el componente ¿Los addeventlisteners se borran?
import styled from 'styled-components';
import fadeIn from '../../styles/animation';
export const Anchor = styled.a`
display: flex;
flex-direction: column;
text-align: center;
text-decoration: none;
width: 75px;
`;
export const Image = styled.img`
${fadeIn()}
border: 1px solid #ddd;
box-shadow: 0px 10px 14px rgba(0, 0, 0, .2);
border-radius: 50%;
height: auto;
overflow: hidden;
object-fit: cover;
height: 75px;
width: 75px;
`;
No se que tan buena sea mi solución, pero hice el reto agregando que se haga la animación cuando aparece y cuando desaparece la lista de categorías.
src/components/ListOfCategories/styles.js
agregue las animaciones
propiedad visibility
el transition
importo animación fadeOut
y la variable showOrHide que paso por las props
import { fadeIn, fadeOut } from '../../styles/animations'
export const List = styled.ul`
display: flex;
overflow: scroll;
width: 100%;
&.fixed{
${props => props.showOrHide ? fadeIn() : fadeOut()}
visibility: ${props => props.showOrHide ? 'visible' : 'hidden'};
background: #fff;
border-radius: 60px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
left: 0;
margin: 0 auto;
max-width: 400px;
padding: 5px;
position: fixed;
right: 0;
top: -20px;
transform: scale(.5);
z-index: 2;
transition: visibility 1s;
}
`
src/styles/animations.js
la animación fadeOut
const fadeOutKeyframes = keyframes`
from{
filter: blur(0);
opacity: 1;
}
to {
filter: blur(5px);
opacity: 0;
}
`
export const fadeOut = ({ time = '1s', type = 'ease' } = {}) =>
css`animation: ${time} ${fadeOutKeyframes} ${type};`
src/components/ListOfCategories/index.js
siempre se renderizan las 2 listas de categorías
el estado showFixed lo paso al componente en la propiedad showOrHide
const renderList = (fixed) => {
return (
<List showOrHide={showFixed} className={fixed ? 'fixed' : ''}>
{
categories.map(category => <Item key={category.id}><Category {...category} /></Item>)
}
</List>
)
}
return (
<>
{renderList()}
{renderList(true)}
</>
)
esta parte esta bien interesante
https://petgram.flavs.now.sh/
aqui pueden ver mi resultado
solo agregue en:
&.fixed
${fadeIn()}
ease;
y queda ya que los estilos estan definidos
Puse el fadeIn antes de que lo dijera en el final 😯
Mi solucion:
src\components\ListOfCategories\Styles.js
import styled from 'styled-components'
import { fadeIn } from '../../Styles/animation'
export const List = styled.ul`
display: flex;
overflow: scroll;
width: 100%;
&::-webkit-scrollbar {
display: none;
}
&.fixed {
${fadeIn({ time: '1s' })}
background: #FFF;
border-radius: 60px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
left: 0;
margin: 0 auto;
max-width: 400px;
padding: 5px;
position: fixed;
right: 0;
top: -20px;
transform: scale(0.5);
z-index: 1;
}
`
export const Item = styled.li`
padding: 0 8px;
`
NO entendi esta parte
document.addEventListener('scroll', onScroll)
return () => document.removeEventListener('scroll', onScroll)
}, [showFixed])```
no me quedó muy claro lo de las dependencias… y en la documentación no lo encontré
Por fin pude entender useEffect! Muchas gracias!
Muy sencillo utilizar el fadeIn ya lo teniamos preparado para usar en cualquier otro .css
Custom Hooks
Son infinitos porque podemos crear nuestro propio custom hooks.
Podemos utilizar un hooks de forma que se pueda reutilizar la lógica en diferentes componentes. Otra ventaja es la separación de conceptos que nos permite separar diferentes conceptos en diferentes hooks, agrupando mejor que estamos haciendo en cada parte de nuestro código.
Son 100% retro compatibles, no tenemos que volver a escribir nuestro código para adaptarlo a los hooks pasamos progresivamente nuestra aplicación a utilizar hooks cuando tenga sentido.
Mejor transpilación con Babel. Mejor Performance, la ejecución de una función es más rápida que evaluar una clase.
Dato curioso
Fragment se puede usar de 3 formas
React.Fragment //Usando React para acceder a esta propiedad
Fragment //Importandolo
<></> //isin importar ni llamar por propiedad
Aplicar el efecto de fadeIn se puede hacer reutilizando la animación usada en las imágenes de las cardas:
export const List = styled.ul`
display: flex;
overflow: scroll;
width: 100%;
&::-webkit-scrollbar {
display: none;
}
&.fixed {
${fadeIn({time: '0.8s'})}
background: white;
border-radius: 60px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
left: 0;
margin: 0 auto;
max-width: 400px;
padding: 5px;
position: fixed;
right: 0;
top: -20px;
transform: scale(.5);
z-index: 1;
}
` ```
la animacion cuando aparezca el fixed primero en el styled List pongo esto
${({ fixed }) => fixed ? fadeIn() : ''};
luego le paso esa prop
<List fixed className={fixed ? 'fixed' : ''}>
Ya le voy agarrando cariño al useEffect, la aplicación va a al 100
Todavía no logro sacarle la barra de scroll a las categorías. Probé con webkit y si lo saca pero el tema es que el mouse no escrolea horizontalmente. alguna sugerencia?
Hola, les dejo mi repositorio de este proyecto, pero hecho en Nextjs:
https://github.com/danyel117/petgram-platzi/tree/floating_categories
&.fixed{
${fadeInd({ time: '2s', type: 'ease' })}
}
https://clonegram-client-epqhak6k4.now.sh/
dejaré esto por aquí xd
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?
o inicia sesión.