Tutorial 👉 Video
--
¿Te apasiona la música y la programación? En este tutorial paso a paso, aprenderás a desarrollar una aplicación web que utiliza la API de Spotify para visualizar tus canciones y artistas más escuchados. Este video está diseñado para guiarte desde la configuración inicial hasta el despliegue, explicando cada detalle del proceso.
☑️ ¿Qué aprenderás?
- Configurar Auth.js para autenticación segura con Spotify.
- Integrar la API de Spotify para obtener datos como "Top Tracks" y "Top Artists".
- Diseñar componentes dinámicos y atractivos usando Next.js y TailwindCSS.
- Optimizar tu aplicación utilizando hooks avanzados como
useCallback
,useMemo
yuseContext
. - Manejar scopes de autenticación y realizar fetchs eficientes a los endpoints de Spotify.
☑️ Características del proyecto:
- Períodos personalizados para tus datos: últimas 4 semanas, 6 meses y todo el tiempo.
- Presentación de datos en un carousel con tarjetas detalladas:
- Tracks: Título y artista.
- Artists: Nombre y género musical.
☑️ Tecnologías utilizadas:
Next.js, TypeScript, TailwindCSS, shadcn/ui y Auth.js.
- Clona este repositorio:
git clone https://github.com/tu-usuario/spotify-visualization.git
- Instala las dependencias:
npm install --force
- Ejecuta la aplicación:
npm run dev
- Autentícate con tu cuenta de Spotify y explora tus datos musicales.
useCallback
es un hook de React que memoiza una función para evitar que se recree en cada renderizado, salvo que sus dependencias cambien.
- Primer renderizado: Crea y guarda la función.
- Renderizados posteriores:
- Si las dependencias no cambian, devuelve la misma instancia de la función.
- Si alguna dependencia cambia, crea una nueva función.
- Reduce renderizados innecesarios en componentes hijos.
- Mejora el rendimiento al evitar la recreación de funciones costosas.
const fetchDatos = useCallback(async () => {
if (status !== 'authenticated') return;
try {
setLoading(true);
const accessToken = await getUserAccessToken();
const data = filterType === 'tracks'
? await getCurrentUserTopTracks(accessToken)
: await getCurrentUserTopArtists(accessToken);
if (data && 'items' in data) {
setDatos(data);
}
} catch (error) {
console.error('Fetch error:', error);
} finally {
setLoading(false);
}
}, [filterType, status]);
useMemo
memoiza el resultado de una computación para evitar recalcularlo innecesariamente, salvo que las dependencias cambien.
- Primer renderizado: Calcula y guarda el valor.
- Renderizados posteriores:
- Si las dependencias no cambian, devuelve el mismo valor memoizado.
- Si alguna dependencia cambia, recalcula el valor.
- Evita la creación de nuevos objetos en cada renderizado.
- Optimiza componentes que dependen de valores complejos.
const contextValue = useMemo(() => ({
datos,
setDatos,
filterType,
setFilterType,
loading
}), [datos, filterType, loading]);
export const SpotifyContextProvider = ({ children }: { children: React.ReactNode }) => {
const [datos, setDatos] = useState<ITopTracks | ITopArtists>(dumbData);
const [filterType, setFilterType] = useState<'tracks' | 'artists'>('tracks');
const [loading, setLoading] = useState(false);
const { status } = useSession();
const fetchDatos = useCallback(async () => {
if (status !== 'authenticated') return;
try {
setLoading(true);
const accessToken = await getUserAccessToken();
const data = filterType === 'tracks'
? await getCurrentUserTopTracks(accessToken)
: await getCurrentUserTopArtists(accessToken);
if (data && 'items' in data) {
setDatos(data);
}
} catch (error) {
console.error('Fetch error:', error);
} finally {
setLoading(false);
}
}, [filterType, status]);
useEffect(() => {
fetchDatos();
}, [fetchDatos]);
const contextValue = useMemo(() => ({
datos,
setDatos,
filterType,
setFilterType,
loading
}), [datos, filterType, loading]);
return (
<SpotifyContext.Provider value={contextValue}>
{children}
</SpotifyContext.Provider>
);
};
useCallback
minimiza la recreación de la funciónfetchDatos
.useMemo
optimiza el valor del contexto para evitar renderizados innecesarios.- Ambos hooks contribuyen a mejorar la eficiencia del componente.
- Usa
useCallback
para funciones que se pasan como props a componentes hijos. - Usa
useMemo
para computaciones complejas o valores referenciados en dependencias de otros hooks. - No abuses de ellos: úncamente cuando notes problemas de rendimiento.
Las contribuciones son bienvenidas. Si tienes sugerencias o encuentras errores, por favor abre un issue o envía un pull request.