Ejercicios 7.7.-7.20.
Estos ejercicios presuponen que ya has completado los ejercicios 5.24-5.28. Si no lo has hecho, complétalos primero.
7.7: Frontend y backend en el mismo repositorio
Durante el curso, el frontend y el backend de la aplicación BlogList han estado en repositorios separados. Una práctica habitual en proyectos reales consiste en colocar ambos en un único repositorio, lo que simplifica el despliegue y facilita compartir código entre ellos.
Lee la sección Frontend y backend en el mismo repositorio del material y reestructura tu aplicación en consecuencia. Coloca el código fuente del frontend y del backend en el mismo repositorio, manteniendo separados sus archivos package.json.
Asegúrate de que el flujo de desarrollo sigue funcionando: ejecutar npm run dev en el directorio del frontend debe iniciar el servidor de desarrollo de Vite con recarga en caliente, igual que antes. Comprueba también que el build de producción funciona: el backend debe poder servir el frontend compilado como sitio estático mediante un comando como npm run build && npm start —o scripts equivalentes que definas—.
Nota: si después de reorganizar el repositorio aparecen errores extraños de dependencias, la solución más segura suele ser eliminar todos los directorios node_modules y volver a ejecutar npm install desde cero en cada directorio pertinente.
7.8: Límite de errores
Los errores de una aplicación React que no se capturen en ningún lugar producen una página en blanco. Esto no ofrece una buena experiencia de usuario. La solución estándar de React es el concepto de límite de errores: un componente que envuelve una parte del árbol de componentes, captura los errores de renderizado que se producen en su interior y muestra una interfaz alternativa en vez de bloquear toda la página.
Lee la sección Límite de errores del material. Después, añade a tu aplicación un componente de límite de errores que capture los errores de renderizado y muestre un mensaje comprensible en vez de una página en blanco.
El límite de errores debe añadirse de manera que la barra de navegación quede fuera de él. Si se produce un error de renderizado en cualquier lugar del resto de la aplicación, el límite lo captura y muestra un mensaje fácil de entender como este:
Puedes simular un error de renderizado lanzando temporalmente una excepción dentro de uno de tus componentes, por ejemplo:
const BlogList = ({ blogs }) => {
throw new Error('simulated error')
return (
)
}
7.9: Rutas inexistentes
La aplicación también presenta otro tipo de error. Si el usuario intenta navegar a una ruta que no existe, como
o
el resultado es una página en blanco. Corrige el enrutamiento para que al navegar a una ruta inexistente se muestre un mensaje apropiado de «Página no encontrada». La ruta comodín de React Router (path="*") es la herramienta adecuada: coincide con cualquier ruta que no cubra ninguna otra. El resultado debe tener este aspecto:
7.10: Formateo automático del código
En las partes anteriores utilizamos ESLint para garantizar que el código siguiera las convenciones definidas. Prettier es otro enfoque para el mismo problema. Según la documentación, Prettier es an opinionated code formatter, es decir, no solo controla el estilo del código, sino que también lo formatea según su definición.
Prettier es fácil de integrar en el editor de código para que el archivo se formatee automáticamente al guardarlo.
Incorpora Prettier a tu aplicación y configúralo para que funcione con tu editor.
Gestión del estado: Zustand
Hay dos versiones alternativas entre las que elegir para los ejercicios 7.11-7.14: puedes gestionar el estado de la aplicación con Zustand o con React Query y Context. Si quieres maximizar tu aprendizaje, ¡deberías hacer ambas versiones!
Nota: si completaste la parte 6 utilizando Redux, por supuesto puedes usar Redux en vez de Zustand en esta serie de ejercicios.
7.11: Zustand, paso 1
Refactoriza la aplicación para utilizar Zustand en la gestión de los datos de las notificaciones.
7.12: Zustand, paso 2
Ten en cuenta que este ejercicio y los dos siguientes son bastante laboriosos, pero increíblemente educativos.
Almacena la información de las entradas de blog en el store de Zustand. En este ejercicio basta con que puedas ver los blogs del backend y crear un nuevo blog.
Puedes gestionar el estado del inicio de sesión y de la creación de nuevas entradas de blog mediante el estado interno de los componentes de React.
7.13: Zustand, paso 3
Amplía tu solución para que vuelva a ser posible dar «me gusta» a un blog y eliminarlo.
7.14: Zustand, paso 4
Almacena la información del usuario que ha iniciado sesión en el store de Zustand.
Gestión del estado: React Query y Context
Hay dos versiones alternativas entre las que elegir para los ejercicios 7.11-7.14: puedes gestionar el estado de la aplicación con Zustand o con React Query y Context. Si quieres maximizar tu aprendizaje, ¡deberías hacer ambas versiones!
7.11: React Query y Context, paso 1
Refactoriza la aplicación para utilizar el hook useReducer y el contexto en la gestión de los datos de las notificaciones.
7.12: React Query y Context, paso 2
Utiliza React Query para gestionar el estado de las entradas de blog. Para este ejercicio basta con que la aplicación muestre los blogs existentes y permita crear correctamente un nuevo blog.
Puedes gestionar el estado del inicio de sesión y de la creación de nuevas entradas de blog mediante el estado interno de los componentes de React.
7.13: React Query y Context, paso 3
Amplía tu solución para que vuelva a ser posible dar «me gusta» a un blog y eliminarlo.
7.14: React Query y Context, paso 4
Utiliza la Context API para gestionar los datos del usuario que ha iniciado sesión.
7.15: Limpieza del código
Lo más probable es que tu aplicación contenga código que gestiona el usuario que ha iniciado sesión mediante localStorage en varios lugares:
const userJSON = window.localStorage.getItem('loggedBlogappUser')
window.localStorage.setItem('loggedBlogappUser', JSON.stringify(user))
window.localStorage.removeItem('loggedBlogappUser')
Extrae esta lógica a un módulo de servicio específico, src/services/persistentUser.js, que exporte las siguientes funciones:
const getUser = () => { ... }
const saveUser = (user) => { ... }
const removeUser = () => { ... }
Sustituye todos los accesos directos a localStorage de la aplicación por llamadas a estas funciones.
Utiliza también en los formularios el hook useField presentado anteriormente en esta parte.
El resto de las tareas son comunes a las versiones con Zustand y con React Query.
7.16: Vista de usuarios
Implementa una vista en la aplicación que muestre toda la información básica relacionada con los usuarios:
7.17: Vista de un usuario
Implementa una vista para cada usuario que muestre todas las entradas de blog añadidas por él:
Puedes acceder a esta vista haciendo clic en el nombre del usuario en la vista que enumera todos los usuarios:
7.18: Comentarios, paso 1
Implementa la funcionalidad para comentar las entradas de blog:
Los comentarios deben ser anónimos, es decir, no deben estar asociados al usuario que los dejó.
En este ejercicio basta con que el frontend muestre los comentarios que la aplicación recibe del backend.
Un mecanismo apropiado para añadir comentarios a una entrada de blog sería una petición HTTP POST al endpoint api/blogs/:id/comments.
7.19: Comentarios, paso 2
Amplía tu aplicación para que los usuarios puedan añadir comentarios a las entradas de blog desde el frontend:
7.20: Estilos
Mejora la apariencia visual de las nuevas funcionalidades de tu aplicación utilizando las técnicas tratadas en la parte 5.
Este era el último ejercicio de esta parte del curso. Es hora de subir tu código a GitHub y marcar todos los ejercicios que hayas completado en el sistema de entrega de ejercicios.