Programación Reactiva Con React NodeJS MongoDB Demo
Programación Reactiva Con React NodeJS MongoDB Demo
❝Se proactivo antes los cambios, pues una vez que llegan no tendrás tiempo para
reaccionar❞
Página | 2
Datos del autor:
Ciudad de México
e-mail: [email protected]
Autor y Editor
Composición y redacción:
Edición:
Portada
Primera edición
3 | Página
Acerca del autor
Oscar Blancarte es originario de Sinaloa, México donde estudió la carrera de Ingeniería
en Sistemas Computacionales y rápidamente se mudó a la Ciudad de México donde
actualmente radica.
A lo largo de su carrera ha trabajado para diversas empresas del sector de TI, entre las
que destacan su participación en diseños de arquitectura de software y consultoría para
clientes de los sectores de Retail, Telco y Healt Care.
Página | 4
Otras obras del autor
En este libro trato de ir un poco más allá de los ejemplos típicos para crear cosas realmente
increíbles. Por ejemplo:
5 | Página
Utilizar estrategias para cambiar la forma en que los usuarios son autenticados en
la aplicación; como podría ser por Base de datos, Webservices, etcétera.
Crear tu propia máquina de estados para administrar el ciclo de vida de tu servidor.
Éstos son sólo algunos de los 25 ejemplos que abordaremos en este libro, los cuales
están acompañados, en su totalidad, con el código fuente para que seas capaz de
descargarlos, ejecutarlos y analizarlos desde tu propia computadora.
Adquiérelo en https://patronesdediseño.com
Página | 6
Agradecimientos
Este libro tiene una especial dedicación a mi esposa Liliana y mi hijo Oscar, quienes son
la principal motivación y fuerza para seguir adelante todos los días, por su cariño y
comprensión, pero sobre todo por apoyarme y darme esperanzas para escribir este
libro.
A mis padres, quien con esfuerzo lograron sacarnos adelante, darnos una educación y
hacerme la persona que hoy soy.
A todos mis lectores anónimos de mi blog y todas aquellas personas que, de buena fe,
compraron y recomendaron mi primer libro (Introducción a los patrones de diseño) y
fueron en gran medida lo que me inspiro en escribir este segundo libro.
Finalmente, quiero agradecerte a ti, por confiar en mí y ser tu copiloto en esta gran
aventura para aprender React, NodeJS, MongoDB y muchas cosas más. :)
7 | Página
Prefacio
Cada día, nacen nuevas tecnologías que ayudan a construir aplicaciones web más
complejas y elaboras, con relativamente menos esfuerzo, ayudando a que casi
cualquiera persona con conocimientos básicos de computación puede realizar una
página web. Sin embargo, no todo es felicidad, pues realizar un trabajo profesional,
requiere de combinar muchas tecnologías para poder entregar un producto terminado
de calidad.
Puede que aprender React o NodeJS no sea un reto para las personas que ya tiene un
tiempo en la industria, pues ya están familiarizados con HTML, JavaScript, CSS y JSON,
por lo que solo deberá complementar sus conocimientos con una o dos tecnologías
adicionales, sin embargo, para las nuevas generaciones de programadores o futuros
programadores, aprender React o NodeJS puede implicar un reto a un mayor, pues se
necesita aprender primero las bases, antes de poder programar en una capa más arriba.
Este libro pretende evitarte ese gran dolor de cabeza que yo tuve por mucho tiempo,
pues a lo largo de este libro aprenderemos a utilizar React + NodeJS con Express +
MongoDB y aderezaremos todo esto con Redux, uno de los módulos más populares y
avanzados para el desarrollo de aplicaciones Web profesionales. Finalmente
aprenderemos a crear un API REST completo con NodeJS y utilizando el Estándar de
Autenticación JSON Web Tokens.
El objetivo final de este libro es que aprendas a crear aplicaciones Reactivas con React,
apoyado de las mejores tecnologías disponibles. Es por este motivo que, durante la
lectura de este libro, trabajaremos en un único proyecto que irá evolucionando hasta
terminarlo por completo. Este proyecto será, una réplica de la red social Twitter, en la
cual podremos crear usuarios, autenticarnos, publicar Tweets, seguir a otros usuarios y
ver las publicaciones de los demás en nuestro feed.
Página | 8
Cómo utilizar este libro
Es te libro es en lo general fácil de leer y digerir, pues tratamos de enseñar todos los
conceptos de la forma más simple y asumiendo que el lector tiene poco o nada de
conocimiento de tema, así, sin importar quien lo lea, todos podamos aprender
fácilmente.
Como parte de la dinámica de este libro, hemos agregado una serie de tipos de letras
que hará más fácil distinguir entre los conceptos importantes, código, referencias a
código y citas. También hemos agregado pequeñas secciones de tips, nuevos conceptos,
advertencias y peligros, los cuales mostramos mediante una serie de íconos agradables
para resaltar a la vista.
Texto normal:
Es el texto que utilizaremos durante todo el libro, el cual no enfatiza nada en particular.
Negritas:
Cursiva:
Es texto lo utilizamos para hacer referencia a fragmentos de código como
una variable, método, objeto o instrucciones de líneas de comandos. Pero
también es utilizada para resaltar ciertas palabras técnicas.
Código
Para el código utilizamos un formato especial, el cual permite colorear ciertas palabras
especiales, crear el efecto entre líneas y agregar el número de línea que ayude a
referencia el texto con el código.
1. ReactDOM.render(
2. <h1>Hello, world!</h1>,
3. document.getElementById('root')
4. );
El texto con fondo verdes, lo utilizaremos para indicar líneas que se agregan a un código
existente.
9 | Página
Mientras que el rojo y tachado, es para indicar código que se elimina de un archivo
existente.
Por otra parte, tenemos los íconos, que nos ayudan para resaltar algunas cosas:
Tip
Esta caja la utilizamos para dar un tip o sugerencia que nos
puede ser de gran utilidad.
Importante
Esta caja se utiliza para mencionar algo muy importante.
Error común
Esta caja se utiliza para mencionar errores muy comunes
que pueden ser verdadero dolor de cabeza o para
mencionar algo que puede prevenir futuros problemas.
Documentación
Esta caja se muestra cada vez que utilizamos un nuevo
servicio del API REST, la cual tiene la intención de indicar al
lector donde puede encontrar la documentación del
servicio, como es la URL, parámetros de entrada/salida y
restricciones de seguridad.
Página | 10
Código fuente
Todo el código fuente de este libro está disponible en GitHub y dividido de tal forma
que, cada capítulo tenga un Branch independiente. El código fuente lo puedes encontrar
en:
https://github.com/oscarjb1/books-reactiveprogramming.git
Para ver el código de cada capítulo, solo es necesario dirigirse al listado de branches y
seleccionar el capitulo deseado:
La segunda y más recomendable opción es, utilizar un cliente de Git, como lo es Source
Tree y clonar el repositorio, lo que te permitirá tener acceso a todos los branche desde
tu disco duro.
11 | Página
Requisitos previos
Este libro está diseñado para que cualquier persona con conocimientos básicos de
programación web, puedo entender la totalidad de este libro, sin embargo, debido a la
naturaleza de React y NodeJS, es necesario conocer los fundamentos de JavaScript, pues
será el lenguaje que utilizaremos a lo largo de todo este libro.
También será interesante contar con conocimientos básicos de CSS3, al menos para
entender como declarar selectores y aplicarlos a los elementos de HTML.
Página | 12
INTRODUCCIÓN
Muy lejos han quedado los tiempos en los que Tim Berners Lee, conocido como el padre
de la WEB; estableció la primera comunicación entre un cliente y un servidor, utilizando
el protocolo HTTP (noviembre de 1989). Desde entonces, se ha iniciado una guerra entre
las principales compañías tecnológicas por dominar el internet. El caso más claro, es la
llamado guerra de los navegadores, protagonizado por Netscape Communicator y
Microsoft, los cuales buscaban que sus respectivos navegadores (Internet Explorer y
Netscape) fueran el principal software para navegar en internet.
Durante esta guerra, las dos compañías lucharon ferozmente, Microsoft luchaba por
alcanzar a Netscape, quien entonces le llevaba la delantera y Netscape luchaba para no
ser alcanzados por Microsoft. Como hemos de imaginar, Microsoft intento comprar a
Netscape y terminar de una vez por todas con esta guerra, sin embargo, Netscape se
negó reiteradamente a la venta, por lo que Microsoft inicio una de las más descaradas
estrategias; amenazo con copiar absolutamente todo lo que hiciera Netscape si no
accedían a la venta.
En esta carrera por alcanzar a Netscape, ambas empresas empezaron a lanzar releaces
prácticamente cada semana, y semana con semana, los navegadores iban agregando
más y más funcionalidad, lo cual podría resultar interesante, pero era todo lo contrario.
Debido a la guerra sucia, ninguna empresa se apegaba a estándares, que además eran
prácticamente inexistentes en aquel entonces. Lo que provocaba que los
programadores tuvieran que escribir dos versiones de una misma página, una que
funcionara en Netscape y otra que funcionara para Internet Explorer, pues las diferencia
que existían entre ambos navegadores era tan grande, que era imposible hacer una
misma página compatible para los dos navegadores.
Para no hacer muy larga esta historia, y como ya sabrás, Microsoft termino ganando la
guerra de los navegadores, al proporcionar Internet Explorer totalmente gratis y
preinstalado en el sistema operativo Windows.
Hasta este punto te preguntarás, ¿qué tiene que ver toda esta historia con React y
NodeJS?, pues la verdad es que mucho, pues durante la guerra de los navegadores
Netscape invento JavaScript. Aunque en aquel momento, no era un lenguaje de
programación completo, sino más bien un lenguaje de utilidad, que permitía realizar
cosas muy simples, como validar formularios, lanzar alertas y realizar algunos cálculos.
Es por este motivo que debemos recordar a Netscape, pues fue el gran legado que nos
dejó.
13 | Página
Retornando a JavaScript, este lenguaje ha venido evolucionando de una manera
impresionante, de tal forma que hoy en día es un lenguaje de programación completo,
como Java o C#. Tan fuerte ha sido su evolución y aceptación que hoy en día podemos
encontrar a JavaScript del lado del servidor, como es el caso de NodeJS, creado por Ryan
Dahl en 2009. De la misma forma, Facebook desarrollo la librería React basada en
JavaScript.
Tanto React como NodeJS funcionan en su totalidad con JavaScript, React se ejecuta
desde el navegador, mientras que NodeJS se ejecuta desde un servidor remoto, el cual
ejecuta código JavaScript.
Página | 14
Índice
Agradecimientos .................................................................................................................................... 7
Prefacio ................................................................................................................................................. 8
Requisitos previos................................................................................................................................ 12
INTRODUCCIÓN ................................................................................................................................... 13
Índice ................................................................................................................................................... 15
15 | Página
React Developer Tools ........................................................................................................................... 64
Resumen ................................................................................................................................................ 66
Página | 16
Jerarquía de los componentes del proyecto......................................................................................... 119
El enfoque Top-down & Bottom-up ..................................................................................................... 120
Top-down ........................................................................................................................................ 120
Bottom-up ....................................................................................................................................... 121
El enfoque utilizado y porque ......................................................................................................... 122
Preparando el entorno del proyecto .................................................................................................... 122
Instalar API REST ............................................................................................................................. 122
Probando nuestra API ..................................................................................................................... 125
Invocando el API REST desde React ..................................................................................................... 128
Mejorando la clase APIInvoker ....................................................................................................... 130
El componente TweetsContainer ......................................................................................................... 133
El componente Tweet .......................................................................................................................... 137
Resumen .............................................................................................................................................. 144
17 | Página
Flujos de actualización de las propiedades .......................................................................................... 183
Flujos de desmontaje de un componente ............................................................................................ 184
Mini Twitter (Continuación 2) .............................................................................................................. 185
El componente TwitterApp ............................................................................................................. 185
El componente TwitterDashboard .................................................................................................. 189
El componente Profile .................................................................................................................... 191
El componente SuggestedUsers ..................................................................................................... 195
El componente Reply ...................................................................................................................... 199
Resumen .............................................................................................................................................. 215
Página | 18
Últimos retoques al proyecto ......................................................................................................... 291
Resumen .............................................................................................................................................. 293
19 | Página
Método PUT .................................................................................................................................... 389
Método DELETE............................................................................................................................... 390
Consideraciones adicionales. .......................................................................................................... 390
Implementemos algunos métodos. ................................................................................................ 390
Trabajando con parámetros ................................................................................................................ 393
Query params ................................................................................................................................. 394
URL params ..................................................................................................................................... 395
Body params ................................................................................................................................... 396
Middleware .......................................................................................................................................... 398
Middleware de nivel de aplicación ................................................................................................. 400
Middleware de nivel de direccionador ........................................................................................... 400
Middleware de terceros.................................................................................................................. 401
Middleware incorporado ................................................................................................................ 401
Error Handler ....................................................................................................................................... 402
Resumen .............................................................................................................................................. 403
Página | 20
Implementar los servicios REST ............................................................................................................ 464
Servicio - usernameValidate ........................................................................................................... 464
Servicio - Signup .............................................................................................................................. 467
Autenticación con JSON Web Token (JWT) ..................................................................................... 470
Servicio - Login ................................................................................................................................ 472
Servicio - Relogin ............................................................................................................................. 476
Servicio - Consultar los últimos Tweets .......................................................................................... 478
Servicio - Consultar se usuarios sugeridos ...................................................................................... 481
Servicio – Consulta de perfiles de usuario ...................................................................................... 484
Servicio – Consulta de Tweets por usuario ..................................................................................... 487
Servicio – Actualización del perfil de usuario ................................................................................. 490
Servicio – Consulta de personas que sigo ....................................................................................... 492
Servicio – Consulta de seguidores .................................................................................................. 494
Servicio – Seguir .............................................................................................................................. 496
Servicio – Crear un nuevo Tweet .................................................................................................... 499
Servicio – Like.................................................................................................................................. 502
Servicio – Consultar el detalle de un Tweet .................................................................................... 505
Documentando el API REST.................................................................................................................. 508
Introducción al motor de plantillas Pug .......................................................................................... 509
API home ......................................................................................................................................... 513
Service catalog ................................................................................................................................ 516
Service documentation ................................................................................................................... 521
Algunas observaciones o mejoras al API.............................................................................................. 523
Aprovisionamiento de imágenes .................................................................................................... 523
Guardar la configuración en base de datos .................................................................................... 525
Documentar el API por base de datos ............................................................................................ 525
Resumen .............................................................................................................................................. 526
21 | Página
Por dónde empezar
Capítulo 1
Hoy en día existe una gran cantidad de propuestas para desarrollar aplicaciones web, y
cada lenguaje ofrece sus propios frameworks que prometen ser los mejores, aunque la
verdad es que nada de esto está cercas de la realidad, pues el mejor framework
dependerá de lo que buscas construir y la habilidad que ya tengas sobre un lenguaje
determinado.
Algunas de las propuestas más interesante para el desarrollo web son, Angular, Laravel,
Vue.JS, Ember.js, Polymer, React.js entre un gran número de etcéteras. Lo que puede
complicar la decisión sobre que lenguaje, librería o framework debemos utilizar.
Desde luego, en este libro no tratamos de convencerte de utilizar React, sino más bien,
buscamos enseñarte su potencial para que seas tú mismo quien pueda tomar esa
decisión.
Solo como referencia, me gustaría listarte algunas de las empresas que actualmente
utilizan React, para que puedas ver que no se trata de una librería para hacer solo
trabajos caseros o de baja carga:
Página | 22
Udemy
Bitbucket
Anypoint (Mule Soft)
Facebook
Courcera
Airbnb
American Express
Atlassian
Docker
Dropbox
Instagram
Reddit
Son solo una parte de una inmensa lista de empresas y páginas que utilizan React como
parte medular de sus desarrollos. Puedes ver la lista completa de páginas que usan
React aquí: https://github.com/facebook/react/wiki/sites-using-react. Esta lista debería
ser una evidencia tangible de que React es sin duda una librería madura y probada.
Un dato que debemos de tener en cuenta, es que React es desarrollado por Facebook,
pero no solo eso, sino que es utilizado realmente por ellos, algo muy diferente con
Angular, que, a pesar de ser mantenido por Google, no es utilizando por ellos para
ningún sitio crítico. Esto demuestra la fe que tiene Facebook sobre React, pero sobre
todo garantiza la constante evolución de esta gran librería.
23 | Página
Introducción a React
React es sin duda una de las tecnologías web más revolucionarias de la actualidad, pues
proporciona todo un mecanismo de desarrollo de aplicaciones totalmente desacoplado
del backend y ejecutado 100% del lado del cliente.
React fue lanzado por primera vez en 2013 por Facebook y es actualmente mantenido
por ellos mismo y la comunidad de código abierto, la cual se extiende alrededor del
mundo. React, a diferencia de muchas tecnologías del desarrollo web, es una librería, lo
que lo hace mucho más fácil de implementar en muchos desarrollos, ya que se
encarga exclusivamente de la interface gráfica del usuario y consume los datos a
través de API que por lo general son REST.
Uno de los datos interesantes de React es que es ejecutado del lado del cliente
(navegador), y no requiere de peticiones GET para cambiar de una página a otra, pues
toda la aplicación es empaquetada en un solo archivo JavaScript (bundle.js) que es
descargado por el cliente cuando entra por primera vez a la página. De esta forma, la
aplicación solo requerirá del backend para recuperar y actualizar los datos.
Página | 24
React suele ser llamado React.js o ReactJS dado que es una librería de JavaScript, por
lo tanto, el archivo descargable tiene la extensión .js, sin embargo, el nombre real es
simplemente React.
Para comprender como trabaja React es necesario entender dos conceptos claves,
los cuales son Server side app (Aplicaciones del lado del servidor) y Single page
app (Aplicaciones de una sola página)
Las aplicaciones del lado del servidor, son aquellas en las que el código fuente de
la aplicación está en un servidor y cuando un cliente accede a la aplicación, el
servidor solo le manda el HTML de la página a mostrar en pantalla, de esta
manera, cada vez que el usuario navega hacia una nueva sección de la página, el
navegador lanza una petición GET al servidor y este le regresa la nueva página.
Esto implica que cada vez que el usuario de click en una sección se tendrá que
comunicar con el servidor para que le regresa la nueva página, creado N
solicitudes GET para N cambios de página. En una página del lado del servidor,
cada petición retorna tanto el HTML para mostrar la página, como los datos que va
a mostrar.
Como vemos en la imagen, el cliente lanza un GET para obtener la nueva página, el
servidor tiene que hacer un procesamiento para generar la nueva página y tiene
25 | Página
que ir a la base de datos para obtener la información asociada a la página de
respuesta. La nueva página es enviada al cliente y este solo la muestra en pantalla.
En esta arquitectura todo el trabajo lo hace el servidor y el cliente solo se limita a
mostrar las páginas que el server le envía.
Las aplicaciones de una sola página se diferencian de las aplicaciones del lado del
servidor debido a que gran parte del procesamiento y la generación de las vistas las
realiza directamente el cliente (navegador). Por otro lado, el servidor solo expone un
API mediante el cual, la aplicación puede consumir datos y realizar operaciones
transaccionales.
En este tipo de arquitectura, se libera al servidor de una gran carga, pues no requiere
tener que estar generando vistas para todos los usuarios conectados.
Como vemos en esta nueva imagen, el cliente es el encargado de realizar las vistas
y realizar algunos procesamientos, mientras que el servidor solo expone un API
para acceder a los datos.
Página | 26
Introducción a NodeJS
NodeJS es sin duda una de las tecnologías que más rápido está creciendo, y que ya hoy
en día es indispensable para cubrir posiciones de trabajo. NodeJS ha sido revolucionario
en todos los aspectos, desde la forma de trabajar hasta que ejecuta JavaScript del lado
del servidor.
Como puedes ver en la imagen, NodeJS es en realidad el motor de JavaScript V8 con una
capa superior de librerías de NodeJS, las cuales se encargan de la comunicación entre el
API de NodeJS y el Motor V8. Adicionalmente, se apoya de la librería Libuv la cual es
utilizada para el procesamiento de entradas y salidas asíncronas.
27 | Página
Que es NodeJS (Según su creador):
Todo esto viene al caso, debido a que NodeJS se ha convertido en unos de los servidores
por excelencia para implementar microservicios, ya que es muy ligero y puede ser
montado en servidores virtuales con muy pocos recursos, algo que es imposible con
servidores de aplicaciones tradiciones como Wildfy, Websphere, Glashfish, IIS, etc.
Página | 28
Hoy en día es posible rentar un servidor virtual por 5 USD al mes con 512mb de RAM y
montar una aplicación con NodeJS, algo realmente increíble y es por eso mi insistencia
en que NodeJS es una de las tecnologías más prometedoras actualmente. Por ejemplo,
yo suelo utilizar Digital Ocean, pues me permite rentar servidores desde 5 usd al mes.
Introducción a MongoDB
MongoDB es la base de datos NoSQL líder del marcado, ya que ha demostrado ser lo
bastante madura para dar vida a aplicaciones completas. MongoDB nace con la idea de
crear aplicaciones agiles, que permita realizar cambios a los modelos de datos si realizar
grandes cambios en la aplicación. Esto es gracias a que permite almacenar su
información en documentos en formato JSON.
Uno de los principales retos al trabajar con MongoDB es entender cómo funciona el
paradigma NoSQL y abrir la mente para dejar a un lado las tablas y las columnas para
pasar un nuevo modelo de datos de Colecciones y documentos, los cuales no son más
que estructuras de datos en formato JSON.
Actualmente existe una satanización contra MongoDB y de todas las bases de datos
NoSQL en general, ya que los programadores habituales temen salir de su zona de
confort y experimentar con nuevos paradigmas. Esta satanización se debe en parte a
dos grandes causas: el desconocimiento y la incorrecta implementación. Me explico, el
desconocimiento se debe a que los programadores no logran salir del concepto de
tablas y columnas, por lo que no encuentra la forma de realizar las operaciones que
normalmente hacen con una base de datos tradicional, como es hacer un Join, crear
procedimientos almacenados y crear transacciones. Y Finalmente la incorrecta
implementación se debe a que los programadores inexpertos o ignorantes utilizan
MongoDB para solucionar problemas para los que no fue diseñado, llevando el proyecto
directo al fracaso.
Es probable que hallas notado que dije que MongoDB no soporta transacciones, y es
verdad, pero eso no significa que MongoDB no sirva, si no que no fue diseñado para
aplicaciones que requieren de transacciones y bloque de registro, un que es posible
simularlos con un poco de programación. Más adelante analizaremos más a detalle
estos puntos.
29 | Página
Bases de datos Relacionales VS MongoDB
Probablemente lo que más nos cueste entender cuando trabajamos con MongoDB, es
que no utiliza tablas ni columnas, y en su lugar, la información se almacena en objetos
completos en formato JSON, a los que llamamos documentos. Un documento se
utiliza para representar mucha información contenida en un solo objeto, que, en una
base de datos relacional, probablemente guardaríamos en más de una tabla. Un
documento MongoDB suele ser un objeto muy grande, que se asemejan a un árbol, y
dicho árbol suele tener varios niveles de profundidad, debido a esto, MongoDB requiere
de realizar joins para armar toda la información, pues un documento por sí solo,
contiene toda la información requerida
1. { 6. {
2. "name": "Juan Perez", 7. "name": "Juan Perez",
3. "age": 20, 8. "age": 20,
4. "tel": "1234567890" 9. "tels": [
5. } 10. "1234567890",
11. "0987654321"
12. ]
13. }
Observemos que los dos objetos son relativamente similares, y tiene los mismos
campos, sin embargo, uno tiene un campo para el teléfono, mientras que el segundo
objeto, tiene una lista de teléfonos. Es evidente que aquí tenemos dos incongruencias
con un modelo de bases de datos relacional, el primero, es que tenemos campos
diferentes para el teléfono, ya que uno se llama tel y el otro tels. La segunda
incongruencia, es que la propiedad tels, del segundo objeto, es en realidad un arreglo,
lo cual en una DB relacional, sería una tabla secundaria unida con un Foreign Key.
Página | 30
Como ya nos podemos dar una idea, en un DB relacionar, es necesario tener estructuras
definidas y relacionadas entre sí, mientras que en MongoDB, se guardan documentos
completos, los cuales contiene en sí mismo todas las relaciones requeridas. Puede sonar
algo loco todo esto, pero cuando entremos a desarrollar nuestra API REST veremos
cómo utilizar correctamente MongoDB.
Hasta este momento, ya hemos hablado de estas tres tecnologías de forma individual,
sin embargo, no hemos analizado como que estas se combinan para crear proyectos
profesionales.
Como vemos en la imagen, React está del lado del FrontEnd, lo que significa que su único
rol es la representación de los datos y la apariencia gráfica. En el BackEnd tenemos a
NodeJS, quien es el intermediario entre React y MongoDB. MongoDB también está en el
Backend, pero este no suele ser accedido de forma directa por temas de seguridad.
Cuando una serie de tecnologías es utilizada en conjunto, se le llama Stack, el cual hace
referencia a todas las tecnologías implementadas. A lo largo de este libro, utilizaremos
el Stack MERN, el cual es el acrónimo de MongoDB, Express, React & NodeJS, estas
31 | Página
tecnologías suelen acompañarse con Webpack y Redux. Puedes encontrar más
información de MERN en la página web: http://mern.io/
Resumen
En este capítulo hemos dado un vistazo rápido a la historia de JavaScript y como es que
ha evolucionado hasta convertirse en un lenguaje de programación completo. De la
misma forma, hemos analizado como es que JavaScript es la base para tecnologías tan
importantes como React y NodeJS.
También hemos analizado de forma rápida a React, NodeJS y MongoDB para dejar claro
los conceptos y como es que estas 3 tecnologías se acoplan para dar soluciones de
software robustas.
Página | 32
Introducción al proyecto Mini Twitter
Capítulo 5
Hasta este punto, ya hemos visto muchas de las características de React y ya estamos
listo para empezar a desarrollar el proyecto Mini Twitter, el cual es una réplica de la
famosa red social Twitter. Esta app no busca ser una copia de la aplicación, si no ejemplo
educativo que nos lleve de la mano para construir una aplicación Totalmente funcional
utilizando las tecnologías de React, NodeJS y MongoDB.
Debido a que la aplicación Mini Twitter abarca el desarrollo del FrontEnd y el BankEnd,
organizaremos el libro de tal forma que, primero veremos toda la parte del FrontEnd,
en donde aprenderemos React y utilizaremos Bootstrap como framework para hacer
nuestra aplicación Responsive. Una vez terminada la aplicación, tendremos un capítulo
especial para estudiar Redux y cómo implementarlo en nuestro proyecto. En segundo
lugar, veremos el desarrollo de un API REST, utilizando NodeJS + Express, el popular
framework de NodeJS para desarrollo web. Adicional, veremos todo lo referente a
MongoDB, como crear los modelos, conectarnos, realizar consultar y actualizar los
datos.
Antes de iniciar con el desarrollo del proyecto Mini Twitter, es importante entender lo
que vamos a estar desarrollando, y es por eso que, este capítulo está especialmente
dedicado a ello. Lo primero que haremos será dar un tour por la aplicación terminada,
luego regresaremos para analizar cómo está compuesta, y finalmente iniciar con el
desarrollo.
Página | 110
Página de inicio
Perfil de usuario
111 | Página
Editar perfil de usuario
La página de perfil puede cambiar de estado a editable, la cual permite cambiar la foto
de perfil, banner, nombre y la descripción:
Observemos que el banner, cómo la foto, cambian, agregando un ícono de una cámara,
la cual, al poner el mouse enzima se subrayada de color naranja, habitando cargar una
foto nueva con tan solo hacer clic. También, donde aparece el nombre de usuario y
descripción, pasan a ser editables.
Página de seguidores
Página | 112
Detalle del Tweet
También es posible ver el detalle de cada Tweet, para ver los comentarios que tiene y
agregar nuevos.
Otra de las páginas que cuenta la aplicación son las clásicas pantallas de iniciar sección
(login), la cual autenticarse ante la aplicación mediante usuario y password:
113 | Página
Registro de usuarios (Signup)
Mediante esta página, es posible crear una nueva cuenta para poder acceder a la
aplicación.
Hemos visto un recorrido rápido a lo que será la aplicación de Mini Twitter, pero la
aplicación es engañosa, porque tiene muchas más cosas de las podemos ver a simple
vista, las cuales tenemos que analizar mucho más a detalle. Es por ese motivo, que una
vez que dimos un tour rápido de la aplicación, es hora de verla con rayos X y ver cómo
es que la aplicación se compone y todos los Components que vamos a requerir para
termina la aplicación.
En esta sección analizaremos con mucho detalle todos los componentes que conforman
la aplicación Mini Twitter.
Componente TwitterDashboard
Página | 114
Fig. 59 - Topología de la página de inicio
En la imagen anterior, podemos ver con más detalle cómo está compuesta la página de
inicio. A simple vista, es posible ver 5 componentes, los cuales son:
Adicional a los componentes que podemos ver en pantalla, existe uno más llamado
TwitterApp, el cual envuelve toda la aplicación e incluyendo las demás componentes,
como las páginas de login, signup, y el perfil del usuario.
Componente TweetsContainer
115 | Página
Fig. 60 - Topología del componente TweetsContainer
Componente UserPage
La página de perfil, permite a los usuarios ver su perfil y ver el perfil de los demás
usuarios. Este componente se muestra de dos formas posibles, ya que si estás en tu
propio los datos siempre y cuando estés en tu propio perfil. Por otra parte, si estas en
el perfil de otro usuario, te dará la opción de seguirlo.
Página | 116
Fig. 61 - Topología de la página UserPage
En esta página es posible ver varios componentes que se reúnen para formar la página:
Componente Signup
Este es el formulario para crear un nuevo usuario, el cual solo solicita datos mínimos
para crear un nuevo perfil.
117 | Página
Fig. 62 - Topología de la página Signup
Componente Login
Página | 118
Hasta este momento, hemos visto los componentes principales de la aplicación, lo que
falta son algunas componentes de popup y compontes secundarios en los cuales no me
gustaría nombrar aquí, pues no quisiera entrar en mucho detalle para no perdernos.
Por ahora, con que tengamos una idea básica de cómo está formada la aplicación será
más que suficiente y a medida que entremos en los detalles, explicaremos los
componentes restantes.
La imagen anterior, nos da una fotografía general de toda la aplicación Mini Twitter, en
la cual podemos ver cómo está compuesto cada componente, así como también,
podemos aprecias donde reutilizamos los componentes.
119 | Página
El enfoque Top-down & Bottom-up
Uno de los aspectos más importantes cuando vamos a desarrollar una nueva aplicación,
es determina el orden en que vamos a construir los componentes, pues la estrategia
que tomemos, repercutirá en la forma que vamos a trabajar. Es por este motivo que
vamos a presentar el en enfoque Top-down y Bottom-up para analizar sus diferencias y
las ventajas que traen cada una.
Top-down
Página | 120
modificar el trabajo que ya tenemos echo. Otra de las desventajas, es que casi cualquier
dependencia a otros componentes que requiera algún componente, no existirá y
tendremos que irlos creando al vuelo.
Bottom-up
Este otro enfoque es todo lo contrario que Top-down, pues propone empezar con los
componentes más abajo en la jerarquía, de esta forma, iniciamos con los componentes
que no tienen dependencias y vamos subiendo en la jerarquía hasta llegar al primer
componente en la jerarquía.
Este enfoque es utilizado por los desarrolladores más experimentados, que son capases
de analizar con buen detalle la aplicación a desarrollar. Un mal análisis puede hacer que
replanteemos gran parte de la estructura y con ellos, se genera un gran impacto en el
desarrollo.
121 | Página
El enfoque utilizado y porque
Aunque lo mejor sería utilizar el enfoque Botton-up, la realidad es que apenas estamos
aprendiendo a utilizar React, por lo que aventurarnos a utilizar este enfoque puede ser
un poco riesgoso y nos puede complicar más el aprendizaje. Es por este motivo que en
este libro utilizaremos el enfoque Top-down he iremos construyendo los componentes
a como sea requeridos.
Dado que la aplicación Mini Twitter cuenta con una serie de servicios para funcionar,
deberemos instalar y ejecutar nuestra API Rest antes de empezar a desarrollar, ya que
toda la información que consultemos o actualicemos, será por medio del API REST.
Por el momento no entraremos en detalles acerca del API REST, pues más adelante
hablaremos de cómo desarrollar desde cero, todo el API, publicarlos y prepararlo para
producción. Por ahora, solo instalaremos el API y lo utilizaremos.
Para instalar el API, deberemos bajar la última versión del repo, es decir el branch
“Capitulo-16-Produccion” directamente desde el repo del libro:
https://github.com/oscarjb1/books-reactiveprogramming.git
Página | 122
Fig. 67 - Obtener el String de conexión.
1. module.exports = {
2. server: {
3. port: 3000
4. },
5. tweets: {
6. maxTweetSize: 140
7. },
8. mongodb: {
9. development: {
10. connectionString: "<Copy connection String from Mongo Atlas>"
11. },
12. production: {
13. connectionString: "<Copy connection String from Mongo Atlas>"
14. }
15. },
16. jwt: {
17. secret: "#$%EGt2eT##$EG%Y$Y&U&/IETRH45W$%whth$Y$%YGRT"
18. }
19. }
Aprovecharemos para cambiar el puerto, de tal forma que cambiaremos del 80 al 3000,
como lo podemos ver en la línea 3.
Lo siguiente será configurar el sistema operativo para encontrar nuestra API como un
subdominio del localhost, para ello, realizaremos la siguiente configuración (siempre
como administrador):
123 | Página
En Windows:
1. 127.0.0.1 api.localhost
En Linux
1. 127.0.0.1 api.localhost
En Mac
En Mac, tendremos que hacer exactamente lo mismo que en los anteriores, sin
embargo, el archivo se encuentra en /private/etc/hosts, allí agregaremos la línea:
1. 127.0.0.1 api.localhost
NOTA: Esto hará que cualquier llamada al subdominio api.* se redirija al localhost.
Iniciar el API
Seguido, abrimos la terminal y nos dirigimos a la raíz del API (donde descargamos el
repo), una vez allí ejecutamos el siguiente comando:
npm start.
Con esto, si todo sale bien, habremos iniciado correctamente el API REST.
Página | 124
Probando nuestra API
125 | Página
Creando un usuario de prueba
Antes de poder empezar a utilizar nuestra API, será necesario crear un usuario, por lo
cual, utilizaremos un archivo de utilidad llamado InitMongoDB.js, que se encargará de
esto. El archivo se ve así:
No vamos entrar en los detalles, pues este archivo tiene cosas avanzadas que no hemos
visto aún. Sin embargo, lo muestro por si desean analizarlo.
Por ahora, tendremos que dirigirnos a la terminal y dirigirnos a la carpeta del API (donde
descargamos el código) y ejecutar el comando
node InitMongoDB.js
Página | 126
Fig. 70 - Creación del usuario de prueba.
Si sale algún error, deberemos revisar los datos de conexión a la base de datos.
Username: test
Password: 1234
Para comprobar que todo salió bien, podemos regresar a Compass y ver la colección
profiles, en ella deberíamos ver el usuario:
Del lado izquierdo seleccionamos test profiles y veremos podremos ver los
usuarios. Si no puedes ver la sección “profiles” tendrás que actualizar la vista.
127 | Página
Invocando el API REST desde React
En este punto ya tenemos el API funcionando y listo para ser utilizando, pero debemos
aprender cómo es que un servicio REST es consumido desde una aplicación React.
React proporciona la función fetch la cual se utiliza para consumir cualquier recurso
den la WEB mediante HTTP, por lo que es posible consumir servicios REST mediante el
método POST, GET, PUT, DELETE y PATCH. Esta función recibe dos parámetros para
funcionar, el primero corresponde a la URL en la que se encuentre el servicio y el
segundo parámetro corresponde a los parámetros de invocación, como el Header y el
Body de la petición.
Veamos un ejemplo simple de cómo consumir los Tweets de un usuario. Para esto
deberemos crear una nueva clase en llamada APIInvoker.js en el directorio
/app/utils/. El archivo se ve la siguiente manera:
1. class APIInvoker {
2.
3. invoke(url, okCallback, failCallback, params){
4. fetch(`http://api.localhost:3000${url}`, params)
5. .then((response) => {
6. return response.json()
7. })
8. .then((responseData) => {
9. if(responseData.ok){
10. okCallback(responseData)
11. }else{
12. failCallback(responseData)
13. }
14. })
15. }
16. }
17. export default new APIInvoker();
1. url: String que representa el recurso que se quiere consumir, sin contener el host y
el puerto, ejemplo “/tweets”.
2. okCallback: deberá ser una función, la cual se llamará solo en caso de que el
servicio responda correctamente. La función deberá admitir un parámetro que
representa la respuesta del servicio.
3. failCallback: funciona igual al anterior, solo que este se ejecuta cuando el servicio
responde con algún error.
4. params: Representa los parámetros de invocación HTTP, como son los header y
body.
Página | 128
De estos cuatro parámetros solo dos son requeridos por la función fetch en la línea 4,
la url y params. Cuando el servicio responde, la respuesta es procesada mediante una
promesa (Promise), es decir, una serie de then, los cuales procesan la respuesta por
partes. El primer then (línea 5) convierte la respuesta en un objeto json (línea 6) y lo
retorna para ser procesado por el siguiente then (línea 8), el cual, valida la propiedad ok
de la respuesta, si el valor de esta propiedad es true, indica que el servicio termino
correctamente y llamada la función okCallback, por otra parte, si el valor es false,
indica que algo salió mal y se ejecuta la función failCallback.
Finalmente exportamos una nueva instancia de la clase APIInvoker en la línea 17, con
la finalidad de poder utilizar el objeto desde los componentes de React.
El siguiente paso será probar nuestra clase con un pequeño ejemplo que consulte los
Tweets de nuestro usuario de pruebas, para esto modificaremos la clase App para
dejarla de la siguiente manera:
129 | Página
41. }
42. }
43.
44. render(<App/>, document.getElementById('root'));
No entraremos en los detalles del todo el componente, pues nos es el objetivo de esta
sección, pero lo que solo nos centraremos en la función componentWillMount (línea 14).
Esta función no tiene un nombre aleatorio, si no que corresponde a una de las funciones
del ciclo de vida de los componentes de React, el cual se ejecuta automáticamente justo
antes del que el componente sea montado, es decir, que sea visible en el navegador. Lo
primero que hacemos será preparar los parámetros de la invocación (línea 15). Dentro
de la variable definimos un objeto con las propiedades:
El siguiente paso será invocar el método invoke de la clase APIInvoker que acabamos
de crear, para esto, le estamos enviando la URL del servicio para consultar los Tweets
del usuario test (/tweets/test), el segundo parámetros será la función que se ejecutará
en caso de éxito, la cual solamente actualiza el estado del componente con la respuesta
del servicio, el tercer parámetro es la función de error, la cual solo imprimirá en la
consola los errores retornados.
Finalmente, los Tweets retornados son mostrados en el método render con ayuda de
un <For> para iterar los resultados.
Hasta este punto ya sabemos cómo invocar el API REST desde React, sin embargo,
necesitamos mejorar aún más nuestra clase APIInvoker para reutilizarla en todo el
proyecto.
Lo primero que aremos será quitar todas las secciones Hardcode, como lo son el host y
el puerto y enviarlas a un archivo de configuración externo llamado config.js, el cual
deberemos crear justo en la raíz del proyecto, es decir a la misma altura que los archivos
package.json y webpack.config.js:
Página | 130
Fig. 72 - Archivo config.js
1. module.exports = {
2. debugMode: true,
3. server: {
4. port: 3000,
5. host: "http://api.localhost"
6. }
7. }
131 | Página
26. };
27.
28. this.invoke(url, okCallback, failCallback,params);
29. }
30.
31. invokePOST(url, body, okCallback, failCallback){
32. let params = {
33. method: 'post',
34. headers: this.getAPIHeader(),
35. body: JSON.stringify(body)
36. };
37.
38. this.invoke(url, okCallback, failCallback,params);
39. }
40.
41. invoke(url, okCallback, failCallback,params){
42. if(debug){
43. console.log("Invoke => " + params.method + ":" + url );
44. console.log(params.body);
45. }
46.
47. fetch(`${configuration.server.host}:${configuration.server.port}${url}`,
48. params)
49. .then((response) => {
50. if(debug){
51. console.log("Invoke Response => " );
52. console.log(response);
53. }
54. return response.json()
55. })
56. .then((responseData) => {
57. if(responseData.ok){
58. okCallback(responseData)
59. }else{
60. failCallback(responseData)
61. }
62.
63. })
64. }
65. }
66. export default new APIInvoker();
Como vemos, la clase creció bastante a como la teníamos originalmente, lo que podría
resultar intimidador, pero en realidad es más simple de lo que parece. Analicemos los
cambios. Se han agregado una serie de métodos adicionales al método invoke, pero
observemos que todos se llaman invoke + un método de HTTP, los cuales son:
Si nos vamos al detalle de cada uno de estos métodos, veremos que en realidad
contienen lo mismo, ya que lo único que hacen es crear los parámetros HTTP, como son
los headers y el body, para finalmente llamar al método invoke (sin postfijo). La única
diferencia que tienen estas funciones es que el método invokeGET no requiere un body.
Página | 132
Otro punto interesante a notar es que cuando definimos los header, lo hacemos
mediante la función getAPIHeader, la cual retorna el Content-Type y una propiedad
llamada authorization. No entraremos en detalle acerca de esta, pues lo analizaremos
más adelante cuando veamos la parte de seguridad.
En este punto tenemos lista la clase APIInvoker para ser utilizada a lo largo de toda la
implementación del proyecto Mini Twitter, Y ya solo nos restaría ajustar la clase App.js
para reflejar estos últimos cambios, por lo que vamos a modificar únicamente la función
componentWillMount para que se vea de la siguiente manera:
1. componentWillMount(){
2. APIInvoker.invokeGET('/tweets/test', response => {
3. this.setState({
4. tweets: response.body
5. })
6. },error => {
7. console.log("Error al cargar los Tweets", error);
8. })
9. }
Apreciemos que ya no es necesario definir los parámetros de HTTP, logrando que sea
mucho más simple invocar un servicio.
El componente TweetsContainer
133 | Página
Fig. 73 - Ubicando el componente TweetsContainer
En la siguiente imagen podemos observar una fotografía más detallada del componente
TweetsContainer, en el cual se puedan apreciar los componentes secundarios que
conforman a este.
Este componente tiene dos responsabilidades, la primer, es cargar los Tweets desde el
API y la segunda, es funcionar como un contenedor para ver todos los Tweets que
retorne el API, así como al componente Reply, el cual analizaremos más adelante.
Página | 134
Lo primero que haremos será crear el archivo TweetsContainer.js en el path /app, es
decir, a la misma altura que el archivo App.js y lo dejaremos de la siguiente manera:
135 | Página
Lo primero interesante a resaltar es la función componentWillMount, la cual recupera
dos propiedades, username y onlyUserTweet, las cuales necesitará pasar a la función
loadTweets para cargar los Tweet iniciales. Cabe mencionar que este componente
puede mostrar Tweet de dos formas, es decir, puede mostrar los Tweet de todos los
usuarios de forma cronológica o solo los Tweet del usuario autenticado, y ese es el
motivo por el cual son necesarios estas dos propiedades. Si la propiedad onlyUserTweet
es true, le indicamos al componente que muestre solo los Tweet del usuario
autenticado, de lo contrario, mostrara los Tweet de todos los usuarios. Más adelante
veremos la importancia de hacerlo así para reutilizar el componente.
Usuarios registrados
De momento solo tendremos el usuario test, por lo que de
momento solo podremos consultar los Tweets de este
usuario. Más adelante implementaremos el registro de
usuarios para poder hacer pruebas con más usuarios.
En las líneas 35 a 38 podemos ver como se Iteran todos los Tweets consultados para
mostrar el nombre de usuario del Tweet, el ID y el texto del Tweet.
Al final del archivo también podemos apreciar que hemos definidos los PropTypes y los
DefaultProps, correspondientes a las propiedades onlyUserTweet y profile. El
primero ya lo hemos mencionado, pero el segundo corresponde al usuario autenticado
en la aplicación. De momento no nos preocupemos por esta propiedad, más adelante
regresaremos a analizarla.
Página | 136
Una vez terminado de editar el archivo TweetsContainer, regresaremos al componente
App.js y actualizaremos la función render para que se vea de la siguiente manera:
1. render(){
2. return (
3. <TweetsContainer />
4. )
5. }
El componente Tweet
Hasta este momento solo representamos algunos campos del Tweet para poder
comprobar que el componente TweetsContainer está consultando realmente los datos
desde el API REST, por lo que ahora nos concentraremos en el componente Tweet, el
cual utilizaremos pare representar los Tweets en pantalla.
Lo primero que haremos será crear un nuevo archivo llamado Tweet.js en el path /app
y lo dejaremos de la siguiente manera:
137 | Página
13. render(){
14. let tweetClass = null
15. if(this.props.detail){
16. tweetClass = 'tweet detail'
17. }else{
18. tweetClass = this.state.isNew ? 'tweet fadeIn animated' : 'tweet'
19. }
20.
21. return (
22. <article className={tweetClass} id={"tweet-" + this.state._id}>
23. <img src={this.state._creator.avatar} className="tweet-avatar" />
24. <div className="tweet-body">
25. <div className="tweet-user">
26. <a href="#">
27. <span className="tweet-name" data-ignore-onclick>
28. {this.state._creator.name}</span>
29. </a>
30. <span className="tweet-username">
31. @{this.state._creator.userName}</span>
32. </div>
33. <p className="tweet-message">{this.state.message}</p>
34. <If condition={this.state.image != null}>
35. <img className="tweet-img" src={this.state.image}/>
36. </If>
37. <div className="tweet-footer">
38. <a className={this.state.liked ? 'like-icon liked' :
39. 'like-icon'} data-ignore-onclick>
40. <i className="fa fa-heart " aria-hidden="true"
41. data-ignore-onclick></i> {this.state.likeCounter}
42. </a>
43. <If condition={!this.props.detail} >
44. <a className="reply-icon" data-ignore-onclick>
45. <i className="fa fa-reply " aria-hidden="true"
46. data-ignore-onclick></i> {this.state.replys}
47. </a>
48. </If>
49. </div>
50. </div>
51. <div id={"tweet-detail-" + this.state._id}/>
52. </article>
53. )
54. }
55. }
56.
57. Tweet.propTypes = {
58. tweet: PropTypes.object.isRequired,
59. detail: PropTypes.bool
60. }
61.
62. Tweet.defaultProps = {
63. detail: false
64. }
65.
66. export default Tweet;
Este no es un libro HTML ni de CSS, por lo que no nos detendremos en explicar para que
es cada clase de estilo utilizada ni la estructura del HTML generado, salvo en ocasiones
donde tiene una importancia relacionada con el tema en cuestión.
Página | 138
Lo primero que debemos de resaltar es que este componente recibe dos propiedades,
la primera representa el objeto Tweet como tal y un boolean, que indica si el Tweet debe
mostrar el detalle, es decir, los comentarios relacionados al Tweet.
En la función render podremos ver que este ya es un componente más complejo, pues
retorna un HTML con varios elementos. Por lo pronto te pido que ignores las líneas 14
a 19, pues las explicaremos más adelante y nos centremos en la parte del return.
Quiero que veas que cada Tweet es englobado como un <article> para darle más
semántica al HTML generado. Cada article tendrá un ID generado a partir del ID del
Tweet (línea 22), de esta forma podremos identificar el Tweet más adelante.
En la línea 23 definimos una imagen, la cual corresponde al Avatar del usuario que
publico el Tweet. Fijémonos como tomamos la imagen del estado, mediante
this.state._creator.avatar. De esta misma forma definimos nombre (línea 28),
nombre de usuario (línea 31), el mensaje de tweet (línea 33) y la imagen asociada al
Tweet, siempre y cuando tenga imagen (línea 35).
Las líneas 38 a 48 son las que muestran los iconos de like y compartir, por el momento
no tendrá funcionalidad, pero más adelante regresaremos para implementarla.
En la línea 51 tenemos un div con solo un ID, este lo utilizaremos más adelante para
mostrar el detalle del Tweet, por lo pronto no lo prestemos atención.
1. render(){
2. return (
3. <main className="twitter-panel">
4. <If condition={this.state.tweets != null}>
5. <For each="tweet" of={this.state.tweets}>
6. <Tweet key={tweet._id} tweet={tweet}/>
7. </For>
8. </If>
9. </main>
10. )
11. }
139 | Página
Como último paso tendremos que agregar las clases de estilo CSS al archivo styles.css
que se encuentra en el path /public/resources/css/styles.css. Solo agreguemos lo
siguiente al final del archivo:
Página | 140
61. }
62.
63. .tweet .tweet-body .tweet-name:hover{
64. text-decoration: underline;
65. }
66.
67. .tweet .tweet-body .tweet-username{
68. text-transform: lowercase;
69. color: #999;
70. }
71.
72. .tweet.detail .tweet-body .tweet-user{
73. margin-left: 70px;
74. }
75.
76. .tweet.detail .tweet-body{
77. margin-left: 0px;
78. }
79.
80. .tweet.detail .tweet-body .tweet-name{
81. font-size: 18px;
82. }
83.
84. .tweet-detail-responses .tweet.detail .tweet-body .tweet-message{
85. font-size: 16px;
86. }
87.
88. .tweet.detail .tweet-body .tweet-username{
89. display: block;
90. font-size: 16px;
91. }
92.
93. .tweet.detail .tweet-message{
94. position: relative;
95. display: block;
96. margin-top: 25px;
97. font-size: 26px;
98. left: 0px;
99. }
100.
101. .reply-icon,
102. .like-icon{
103. color: #999;
104. transition: 0.5s;
105. padding-right: 40px;
106. font-weight: bold;
107. font-size: 18px;
108. z-index: 99999;
109. }
110.
111. .like-icon:hover{
112. color: #E2264D;
113. }
114.
115. .like-icon.liked{
116. color: #E2264D;
117. }
118.
119. .reply-icon:hover{
120. color: #1DA1F2;
121. }
122.
123. .like-icon i{
124. color: inherit;
125. }
126.
141 | Página
127. .reply-icon i{
128. color: inherit;
129. }
Guardamos todos los cambios y refrescar el navegador para apreciar cómo va tomando
forma el proyecto.
Página | 142
Una cosa más antes de concluir este capítulo. Hasta el momento hemos trabajado con
la estructura de los Tweets retornados por el API REST, pero no los hemos analizado, es
por ello que dejo a continuación un ejemplo del JSON.
1. {
2. "ok":true,
3. "body":[
4. {
5. "_id":"598f8f4cd7a3b239e4e57f3b",
6. "_creator":{
7. "_id":"598f8c4ad7a3b239e4e57f38",
8. "name":"Usuario de prueba",
9. "userName":"test",
10. "avatar":""
11. },
12. "date":"2017-08-12T23:29:16.078Z",
13. "message":"Hola mundo desde mi tercer Tweet",
14. "liked":false,
15. "likeCounter":0,
16. "replys":0,
17. "image":null
18. }
19. ]
20. }
Lo primero que vamos a observar de aquí en adelante es que todos los servicios
retornados por el API tienen la misma estructura base, es decir, regresan un campo
llamado ok y un body, el ok nos indica de forma booleana si el resultado es correcto y el
body encapsula todo el mensaje que nos retorna el API. Si regresamos al componente
TweetContainer en la línea 22 veremos lo siguiente:
1. this.setState({
2. tweets: response.body
3. })
Observemos que el estado lo crea a partir del body y no de todo el retorno del API.
Ya que conocemos la estructura general del mensaje, podemos analizar los campos del
Tweet, los cuales son:
143 | Página
Resumen
Este capítulo ha sido bastante emocionante pues hemos iniciado con el proyecto Mini
Twitter y hemos aplicados varios de los conceptos que hemos venido aprendiendo a lo
largo del libro. Si bien, solo hemos empezado, ya pudimos apreciar un pequeño avance
en el proyecto.
Por otra parte, hemos visto como instalar el API REST y hemos aprendido como
consumirlo desde React, también hemos analizado la estructura de un Tweet retornado
por el API.
Página | 144