Skip to content

Mis notas del curso de Udemy: React JS + Redux + ES6. Completo ¡De 0 a experto! (español) -

Notifications You must be signed in to change notification settings

Jonatandb/CursoUdemyReactJSReduxES6

Repository files navigation

Mis notas del curso de Udemy: React JS + Redux + ES6

Curso en Udemy: React JS + Redux + ES6. Completo ¡De 0 a experto! (español)

Repositorio: https://github.com/Jonatandb/CursoUdemyReactJSReduxES6

WeatherApp | Jonatandb


  1. Node.js, Npm y Yarn

    https://nodejs.org/es/

    https://classic.yarnpkg.com/en/docs/install#windows-stable

    NodeJs permite escribir aplicaciones del lado del servidor sin bloqueo de entradas/salidas, lo que lo hace muy eficiente.

  1. Gestor de Paquetes NPM y Yarn

    https://www.npmjs.com/

    https://yarnpkg.com/

  1. VSCode

    https://code.visualstudio.com/download

  1. Puntos fuertes de React JS

    https://reactjs.org/

    Posee un gran ecosistema (hay muchas entensiones y recursos relacionados disponibles que extienden sus características)

    Estabilidad y alta retrocompatibilidad La forma en que los creadores de React manejan las versiones y la manera en que van haciendo evloucionar la librería permite que no existan quiebres de compatibilidad entre versiones y que se logre mayor estabilidad general de la plataforma.

    Performance Se logra mediante una librería muy liviana que provee tiempos de carga muy buenos y también posee una buena velocidad de actualización de pantalla, obtenida por renderizaciones parciales inteligentes mediante su virtual dom y el proceso denominado reconciliation.

    A nivel de arquitectura React representa la V de vista del modelo MVC, y suele utilizarse dentro de SPA's (single page applications)

  1. ¡Hola Mundo! Babel, ES6, CodePen

    ¿Que es JSX? https://facebook.github.io/jsx/ https://medium.com/@Thoughtworks_es/qu%C3%A9-demonios-es-jsx-txt-f5841e51f664

    Fundamentalmente, solo es azúcar sintáctico para la función de React:
    React.createElement(component, props, ...children)
    (por eso necesitamos tener a React dentro del scope del proyecto)
    
    Fue creado con la intención de que los preprocesadores (ej. Babel.js) lo transformen en ECMAScript estándar.
    Es decir, el gran propósito de JSX es el de proveer una sintaxis –familiar y concisa (tipo HTML/XML)– para
    	definir estructuras de nodos con propiedades y atributos.
    Existen un par de “reglas” para utilizar JSX:
    	Escribir nuestros propios componentes con capitalización. <App />
    	Escribir los componentes built-in (HTML) con minúsculas. <img />
    JSX no es ni HTML, ni XML; solo se asemeja para ayudar a la legibilidad –para parecer más familiar.
    	Es un simple patrón de composición de funciones pero con una sintaxis similar al HTML/XML.
    En realidad, la mayor diferencia –visual– entre JSX y HTML, es el tener que usar className para agregar una clase,
    	ya que class es una palabra reservada en JS.
    

    Babel https://babeljs.io/

    Babel es un preprocesador de Javascript que entiende versiones de Javascript modernas (como ES6) y las convierte a
    	una versión compatible con la mayoría de los navegadores.
    

    Herramienta que ejecuta Babel online: http://traductor-babel.surge.sh/ Permite que se ingrese JSX y muestra el javascript necesario para crearlo utilizando javascript clásico. Ej:

    lala

    CodePen "Hola mundo" en React: https://codepen.io/correooke/pen/vzwPqX

    Un CodePen es un proyecto online, editable, que permite realizar pruebas de concepto (o incluso proyectos completos) y
    	compartirlos muy fácilmente con quien se desee.
    
    Configuración básica para utilizar con React:
    	Desde las opciones de configuración del CodePen elegir:
    		JavaScript Preprocessor:	Babel
    		Add External Scripts/Pens:
    				https://cdnjs.cloudflare.com/ajax/libs/react/16.4.2/umd/react.production.min.js
    				https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.2/umd/react-dom.production.min.js
    
  1. Creación de app react

    Instalación de paquetes de NPM de manera "global": https://docs.npmjs.com/getting-started/installing-npm-packages-globally

    Instalación de Yarn: https://yarnpkg.com/en/docs/install

    Utilización de npx para crear una nueva aplicación: Weather App npx create-react-app weather-app * Cuando quise ejecutar npx create-react-app me pasaba lo mismo que cuando ejecutaba create-react-app weather-app, que me apareceía un mensaje que decía que estaba usando una versión vieja de create-react-app. Descubrí que estaba instalado create-react-app no solo en la carpeta node_modules global de npm, sino que también en la carpeta de instalación de nodeJS. Al eliminarlo de todos lados pude ejecutar sin problemas: npx create-react-app weather-app y se creó correctamente una nueva aplicación de React.

    Create React App Es una herramienta que facilita crear de una forma fácil una SPA (Single page application) con todas las mejores recomendaciones de Facebook, sponsor principal de React. Esta app tendrá las mejores prácticas incluídas, la configuración correcta de Babel, y la configuración correcta de WebPack (herramienta que toma los distintos archivos de nuestra app y genera lo que se llama un bundle, un paquete con la aplicación listo para ejecutarse.) También viene configurado algo llamado "Hot reload", que es una funcionalidad que recarga nuestra página automáticamente cuando detecta que el código fuente de la misma es modificado. Esto permite ver casi en tiempo real el resultado de las modificaciones que hagamos a nuestra aplicación.

    Primera ejecución de nuestra aplicación: Entrar a la carpeta que se acaba de crear: cd weather-app yarn start // Se puede ejecutar también npm start. Con esto se abrirá una ventana del navegador con la aplicación funcionando.

    Estructura de carpetas: Create-react-app dentro de la carpeta de la aplicación creó las siguientes carpetas: - public Carpeta que posee nuestro archivo princial, index.html, el cual posee un nodo con id "root", que es donde se inyectará nuestra aplicación creada con React. - src Carpeta que contiene todos nuestros componentes, incluído el archivo principal index.js que importa y utiliza el primer componente generado de ejemplo llamado App.

  1. Planificación con Wireframes

    Presentación de la aplicación a desarrollar durante el curso y sus distintas partes y funcionalidades.

    Herramienta para creación de Wireframes (Bosquejos): https://balsamiq.com/

  1. Creación de functional component

    Análisis del archivo "src/App.js", el punto de entrada de la aplicación, el primer componente que "index.js" renderiza.

    Creación de una carpeta para almacenar los componentes: "src/components"

    Simpre que se utiliza JSX para crear un componente, primero se debe importar React (que es quien permite su utilización): import React from 'react'

    Creación del primer componente funcional: "components/WeatherLocation.js" const WeatherLocation = () => {

    Weather Location
    }

    Para que el componente creado pueda ser consumido desde otras partes de la aplicación, el mismo debe ser exportado desde el archivo donde está definido, esto se hace con: export default WeatherLocation

    Importación y uso del componente WeatherLocation desde "src/App.js": import WeatherLocation from './components/WeatherLocation' // ES6 asume que el archivo importado tiene la extensión ".js" por eso // se puede omitir la misma (no es necesario poner "WeatherLocation.js") function App() { return (

    // Uso del componente creado.
    ); } export default App;
  1. VSCode Plugins y extensiones

    Plugins que hacen VSCode más interesante y útil: vscode-icons Reactjs code snippets

  1. ES6 Arrow Functions

    Explicación y ejemplos de funciones flecha.

    • Son el nuevo standard que provee ECMAScript (la especificación de Javascript)
    • Son anónimas: () => { } En caso de necesitar referenciarlas se deben guardar su referencia en una variable: const miFuncion = () => {}
    • No pueden ser utilizadas como constructores.
    • Cuando posee una sola línea no es necesario que tengan la palabra return.
    • Si tiene un solo parámetro, el mismo no necesita ser envuelto en paréntesis Si tiene cero más de un parámentro, entonces si deben ir los paréntesis.
  1. Ejercicio: Creación de componentes e importación

    Creación de componentes: "/components/Location.js" "/components/WeatherData.js"

  1. Componentes WeatherExtraInfo y WeatherTemperature
  1. Uso de parámetros / Herramientas de debugging

    Para pasarle parámetros a un componente, se deben agregar al mismo, en la invocación, atributos con valores. Éstos atributos, serán pasados por React al componente y dentro de los mimsos estará el valor asígnado a cada uno en la invocación al componente. Métodos de debugging: Pablabra clave: debugger; Cuando esta sentencia se deja en el código la misma funciona como un breakpoint, por lo tanto la ejecución de este programa se pausará al llegar a esta línea, pero para que eso suceda se debe debuggear la aplicación.

    Uso de Chrome para debugging: En nuestro sitio web presionamos F12 y se abrirá el panel de herramientas de desarrollador de Chrome, en este panel ir a la solapa denominada "Sources" y recargar la página. Al recargarse la página se vuelve a ejecutar nuestro programa y al llegar la ejecución a la línea con la sentencia "debugger" la misma se detendrá en ese punto, permitiendonos inspeccionar el estado y contenido de las distintas variables y objetos de nuestra aplicación en ese momento. En caso de necesitar puntos de interrupción adicionales, no es necesario modificar el código, sino que se pueden establecer haciendo click en cualquier número de línea de la banda numerada a la izquierda del código en el panel de código de la solapa "Sources", una vez creado un punto cada vez que la ejecución pase por ahí se pausará como con la instrucción "debugger".

  1. Parámetro con Object Destructuring

    https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Operadores/Destructuring_assignment

    Destructuring es una técnica que es parte de ECMAScript 6 que establece que cuando tenemos una propiedad con un nombre que luego queremos asignar a una variable/constante con el mismo nombre que lo propiedad, la podemos asignar de forma directa con esta técnica:

    Sin Destructuring:
    	const MiComponente = (props) => {
    		const city = props.city;
    
    Con Destructuring:
    	const MiComponente = (props) => {
    		const { city } = props;
    
    Si el objeto props tuviera más propiedades que quisiera asignar a constantes, se pueden obtener así:
    	const MiComponente = (props) => {
    		const { city, address } = props;
    
    Simplificando más el código utilizando Destructuring:
    	const MiComponente = ({ city }) => {
    		const city = city;
    
  1. ES6: Object Destructuring

    const obj = { name: 'Jonatandb', nick: 'Jony' }; const { name: myName, nick: myNick } = obj; // Extraigo de obj los valores de name y nick pero lo asigno a nuevas constantes de nombre myName y myNick console.log(myName); // Jonatandb console.log(myNick); // Jony

    Otro caso: const { name, nick } = obj; // Cuando extraigo los valores de las propiedades de un objeto y las asigno a variables del mismo nombre, puedo omitir // la declaración de las variables con el mismo nombre. // Sintaxis no resumida: // const name = obj.name; // const nick = obj.nick;

    Destructuring de arrays: const [x, y] = [1,2]; console.log(x); //-> 1

    Destructuring con valores por defecto: const { x, y = 1 } = {} console.log(x); // undefined console.log(y); // -> 1

    Destructuring de arrays con "elision" (lo que permite omitir una o más posiciones de un array): const [ , , x, y] = ['a', 'b', 'c', 'd'] console.log(x); // -> 'c' console.log(y); // -> 'd'

    Destructuring en conjunto con uso del rest operator (...): Se utiliza para meter en un objeto el resto de valores que queden luego de extraer los deseados. El rest operator se identifica con tres puntos igual que el spread operator, pero su función es diferente. const [x, ...y] = ['a', 'b', 'c', 'd']; console.log(x); // -> 'a' console.log(y); // -> ['b', 'c', 'd']

  1. Parámetros y uso de template string

    Template string: Se tratan de cadenas de texto especiales, porque van entre tildes invertidos texto de la cadena y tiene la particularidad de que pueden contenter variables, pero para que se muestre como parte del string el contenido de la variable, a la misma se la debe encerrar entre el signo de pesos y llaves: ${variable} Ej: const nombre = "Jonatandb"; console.log(Este texto fue mostrado por ${nombre}.); // -> Este texto fue mostrado por Jonatandb.

  1. ES6: Template Strings

    También se conocen como template literals.

  1. Instalación de libreria con npm install o yarn add

    Instalación de componente para mostrar íconos del clima: React-WeatherIcons

    Weather Icons:

    Weather Icons sitio oficial:
    	http://erikflowers.github.io/weather-icons/
    
    React Weather Icons:
    	https://www.npmjs.com/package/react-weathericons
    
    	Instalación:
    		npm install react-weathericons
    
    		Requiere que se agrege también a "index.html" una referencia a un archivo de estilos específico:
    			Weather Icons CDN:
    				https://cdnjs.com/libraries/weather-icons
    
    				Agregar a index.html:
    					<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/weather-icons/2.0.9/css/weather-icons.min.css" />
    

    Uso de Yarn para instalar paquetes: yarn add react-weathericons ** Instala como npm el paquete indicado y actualiza el package.json, solo que funciona mejor que npm al obtener los datos de forma más optimizada.

    Explicación general de la página de NPM.

    Explicación de características generales de GitHub.

  1. Recomendaciones sobre uso de packages externos y ubicación del index.html

    React Weather Icons requiere que se agrege también a "index.html" una referencia a un archivo de estilos específico: Agregado a "public/index.html":

    Weather Icons sitio oficial, para consultar el total de íconos disponibles: http://erikflowers.github.io/weather-icons/

    CDN: Content delivery network, serie de servidores con recursos comunmente muy utilizados por muchos sitios webs, que pueden ser consumidos directamente permitiendo que no necesitemos tener tales recursos en nuestro servidor o en la pc del cliente sino que se descargan en el momento.

  1. Agregar Icono y uso de función en functional component
  1. Utilización de constantes
  1. PropTypes

    Ayuda a validar las propiedades que se le pasan a un componente componente.

    Instalación: yarn add prop-types

    Uso: import PropTypes from 'prop-types'

    Antes de la linea export defual nombreComponente, se escribe la validación por ej. asi:
    	nombreComponente.propTypes = {
    		propiedad1: PropTypes.number,
    		propiedad2: PropTypes.string,
    	}
    A partir de este momento, si cuando se utiliza este componente, se le pasa un tipo de dato diferente al especficado en sus propiedades,
    aparecerá una advertencia en consola indicando tal diferencia.
    
    Lo mismo sucede si a alguna propiedad además de configurarsele su tipo de dato, se le especifica que es requerida, por ej. asi:
    	nombreComponente.propTypes = {
    		propiedad1: PropTypes.number.isRequired,
    		propiedad2: PropTypes.string,
    	}
    En este caso, si se intenta utilizar el componente sin pasarle un valor a su propiedad "propiedad1", también aparecerá una advertencia
    en la consola indicado la falta de un valor para esa propiedad.
    
  1. Validación con PropTypes

    Instalación de extensión "React code snippets" que posee abreviaciones útiles para trabajar con React. Por ej, al escribir ptsr y presionar TAB, se auto-escribe: propTypes.string.isRequired Con esto se pueden especificar los tipos de las propiedades de los componentes de una forma más rápida. También se puede utilizar: pta propTypes.Array ptnr propTypes.number.isRequired y muchas abreviaciones más... (leer documentación de la extensión).

    Agregado de validaciones con PropTypes a todos los componentes del proyecto.

  1. Repaso sobre validaciones de PropTypes

    Validaciones disponibles: (A todas se les puede agregar al final ".isRequired")

    PropTypes.array
    PropTypes.bool
    PropTypes.func
    PropTypes.number
    PropTypes.object
    PropTypes.string
    PropTypes.symbol
    PropTypes.element	Un elemento React
    PropTypes.node 		Cualquier cosa que pueda ser renderizada: numeros, strings, elementos o fragmentos de éstos tipos.
    					Es como una categoría más que PropTypes.element
    PropTypes.instanceOf(Message)	Permite validar que se está pasando una instancia de un objeto específico.
    PropTypes.oneOf(['News', 'Message', etc.])	Permite validar que el tipo sea de alguno de la lista especificada.
    PropTypes.oneOfType([ PropTypes.array, PropTypes.number, PropTypes.instanceOf(Message)]		Similar al anterior.
    PropTypes.arrayOf(PropTypes.number)		Similar al anterior, pero se aclara que se recibirá un array de un tipo especificado.
    PropTypes.shape({
    	color: PropTypes.string,
    	fontSize: PropTypes.number
    })								Permite validar que el valor recibido sea un objeto que tenga las propiedades especificadas.
    PropTypes.any		Permite cualquier tipo de valor.
    
  1. Truco para refactorizar sin problemas: Uso de carpetas e Index.js

    Reorganización de carpetas y renombrado de archivos.

    Aprovechando que cuando se hace import sin especificar la extensión del archivo importado, se busca por defecto tanto un archivo con el nombre especificado (y extensión .js) como una carpeta con dicho nombre (que dentro tenga un archivo index.js), se renombran los archivos para dejar por cada componente una carpeta con el nombre del mismo y dentro un archivo index.js con el componente. Con este refactor se puede pasar de tener una estructura así: /components - Location.js - WeatherData.js - WeatherExtraInfo.js - WeatherLocation.js - WeatherTemperature.js a esta estructura: /components /WeatherLocation - index.js Ex WeatherLocation.js - Location.js /WeatherData - index.js Ex WeatherData.js - WeatherExtraInfo.js - WeatherTemperature.js

  1. Cómo incluir CSS en React

    Agregado de un archivo "styles.css" dentro de cada carpeta de cada componente para especificar sus estilos.

    Agregado de clases a los divs contendores de los componentes.

    Para agregar clases a los componentes, en los divs contendores se debe utilizar "className" en lugar de "class".

  1. Opciones para estilo: CSS, Preprocesadores CSS y CSSModules

    CSS describe cómo se va a ver cada elemento de la página.

    SASS, LESS, son preprocesadores de CSS que extienden las capacidades de CSS agregando variables, reglas anidadas, mixing, importación de archivos y mucho más. Ayudan a mantener grandes hojas de estilo bien organizadas.

    "CSS Modules" es un módulo utilizado dentro del mundo de React que tiene una diferencia con respecto al uso de un archivo "styles.css" ya que utiliza un alias para el mismo.

  1. CSS en React "Under the hood"

    WebPack cuando comprime el contenido de nuestra aplicación, mete tanto el javascript como el css, todo junto, en un archivo llamado "bundle.js" Este archivo en desarrollo es legible, pero en productivo está minificado para reducir el tamaño al máximo para que descargue enseguida del servidor y la aplicación esté disponible lo más rápido posible en el navegador del usuario.

  1. Aplicación de estilos CSS
  1. Estilos componente WeatherTemperature
  1. Estilos componente WeatherExtraInfo
  1. External Font y otros detalles

    Agregado de una fuente externa desde la página de fuentes de Google: fonts.google.com Desde la página de la fuente "Roboto": https://fonts.google.com/specimen/Roboto hacer click en "SELECT THIS FONT" para que aparezca el código HTML necesario para utilizar esta fuente en nuestra aplicación. Ir al archivo "index.html" y en el Head pegar el código obtenido:

    Luego, desde cualquier archivo css, se puede hacer uso de la fuente mediante: font-family: 'Roboto', sans-serif;
  1. Herramientas de debugging para estilo y CSSMatic

    Uso de las herramientas de desarrollador de Chrome para inspeccionar los elementos HTML y sus estilos aplicados y manipularlos para revisar ajustes.

    CSSMatic.com Está pagina contiene herramientas online que podemos utilizar en nuestras hojas de estilo. Posee un generador de gradientes, el cual manipulamos en linea y luego copiamos el código generado para utilizarlo en nuestra aplicación. Posee también un generador de sombras, otro de bordes, otro de texturas...

    CSS-Tricks.com Tutoriales de calidad para aprender a trabajar con Flexbox, CSS Grid, entre otros.

  1. Doble Destructuring

    Se utiliza cuando se desea extraer de un objeto con varios niveles de propiedades, algunos de sus valores. Por ej, teniendo el siguiente obtejo: const miObjeto = { propiedad1: 123, data: { propiedada: 'a', propiedadb: 'b' } } Se puede hacer doble destructuring y extraer solo los valores de las propiedades de la propiedad data: const { data: { propiedada, propiedadb } } = miObjeto; A partir de este momento, tengo disponibles mediante las constantes propiedada y propiedadb, los valores 'a' y 'b' respectivamente.

  1. Utilización de PropType.Shape

    Se utiliza para especificar que una propiedad de un componente va a recibir un objeto con una forma específica y con propiedades con valores de los tipos especificados: WeatherData.propTypes = { data: PropTypes.shape({ temperature: PropTypes.number.isRequired, weatherState: PropTypes.string.isRequired, humidity: PropTypes.number.isRequired, wind: PropTypes.string.isRequired, }), } En este caso se utilza para declarar que el componente WeatherData tiene una propiedad llamada 'data' que recibe como valor un objeto el cual tiene las propiedades 'temperature', 'weatherState', 'humidity' y 'wind', con los tipos de datos específicados.

  1. Cómo transformar un functional en un class Component
    • Se debe modificar el componente funcional, por ej:

        const MiComponente = () => {
            return (
                <div>
                    <span>Este es mi componente</span>
                </div>
            )
        }
      
    • De la siguiente manera:

        import React, { Component } from 'react';
        class MiComponente extends Component {
            render() {
                return (
                    <div>
                        <span>Este es mi componente</span>
                    </div>
                );
            }
        }
      
  1. Evento OnClick y manejo de State
    • Para poder tener estado en un componente, el mismo debe ser un componente de clase.

    • Además, el componente de clase, debe tener definido el método constructor(), y el mismo por dentro debe llamar al constructor de su clase padre:

        constructor(props) {
            super(props)
        }
      
    • Una vez hecho esto, se puede establecer el estado inicial del componente, ej:

        class MiComponente extensión Component {
            constructor() {
                super();
                this.state = {
                    mensaje: 'Estado inicial del componente',
                }
            }
        }
      
    • Luego, mediante interacciones del usuario con el componente, por ejemplo haciendo click, se puede alterar este estado, lo que hará que el componente se renderice, dibujandose de nuevo y por ende mostrando el nuevo estado:

        class MiComponente extensión Component {
            constructor() {
                super();
                this.state = {
                    mensaje: 'Estado inicial del componente',
                }
            }
            handleClick = () => {
                console.log('Se clickeó el div');
                this.setState({
                    mensaje: 'Este mensaje aparece como resultado de modificar el state'
                })
            }
            render() {
                const mensaje = this.state;
                return (
                    <div onClick={this.handleClick}>
                        <span>Mensaje a mostrar: {mensaje}</span>
                    </div>
                );
            }
        }
      
    • Es muy importante tener en cuenta que para modificar el state de un componente, no se puede llamar a this.state y asignarle un nuevo valor, como se hace durante la inicialización en el constructor, ya que arrojará un error por la consola y no surtirá efecto. Lo que se debe hacer en su lugar es utilizar la funcionalidad this.setState(), la cual recibe como valor un objeto con la propiedad que se desea agregar o actualizar al state del componente.

  1. SetState (updater)

    Explicación de lo que sucede al setear el estado inicial y al actualizarlo utilizando mediante el uso de this.setState({})

  1. React Developer Tools para Chrome

    Instalación de extensión para Chrome que facilita el debugging de aplicaciones React:

    React Developer Tools
    https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=es
    

    Esta extensión agregar a las herramientas de desarrollador de Chrome, un par de solapas que permite inspeccionar los componentes que componen nuestra aplicación. Permite buscar componentes por nombre, clickear los componentes de la página para mostrar sus propiedades y los valores de la misma. Permite que sean modificadas las propiedades para ver en tiempo real los resultados. Permite activar la opción "Highlight Updates", lo que muestra un borde resaltado en los componentes cuando los mismos se actualizan. Permite también revelar dentro de que componente se encuentra un elemento HTML al que le hicimos click luego de seleccionar "Inspeccionar elemento".

  1. Api Rest OpenWeatherMap

    Explicación de funcionamiento del servicio de OpenWeatherMap.

    OpenWeatherMap: Servicio gratuito que provee datos del clima

    Página principal:
    				https://openweathermap.org/
    
    Documentación de la API:
    				https://openweathermap.org/api
    
    Guía de uso - How to start:
    				https://openweathermap.org/appid
    
    "Ciudad Autónoma de Buenos Aires", "id": 3433955,
    
  1. Fetch y solapa de debugging Network de Chrome

    fetch es una función incluída en el core de JavaScript que realiza peticiones http.

    fetch al ser relativamente nueva, no es totalmente compatible con navegadores antiguos, por lo que se recomienda en todo caso utilizar: Axios.

    Explicación y uso de la solapa Network de las herramientas de desarrollador de Chrome.

  1. Promises

    Una promise se utiliza para procesamientos asincronicos Su resultado puede ser obtenido ahora, en un futuro o nunca. Estados: Pendiente Cumplida Rechazada

    Ciclo de vida de una promise: Inicialmente se encuentra en estado Pending Cuando se ejecuta puede pasar al estado Fulfill (Cumplida) o al estado Rejected (Rechazada). Si termina en estado Fulfill se ejecuta entonces la funcionalidad dentro de la llamada a ".then()", then() recibe como parámetro el resultado de la ejecución de la promise y se puede hacer en ese momento lo que se necesite, incluso hacer una nueva llamada a otra Promise por ejemplo. En caso de terminar Rejected, se va a ejecutar la funcionalidad dentro de ".catch()", si hubiera uno. Las promises se pueden encadenar.

    Ej: let promesa = new Promise( (resolve, rejected) => { setTimeout( () => { resolve("Éxito"); // Esta promesa al ser ejecutada se resolverá exitosamente devolviendo el string "Éxito". }, 2000); // La promesa tardará 2 segundos en resolverse exitosamente. }) console.log("Ejecución de la promise..."); promesa.then( msg => { console.log("Mensaje devuelto por la promesa: ", msg); }) console.log("Fin de la ejecución de la promise.");

    El resultado por consola de esta ejecución es el siguiente:
    	Ejecución de la promise...
    	Fin de la ejecución de la promise.
    	Mensaje devuelto por la promesa: Éxito
    * Esto es así porque la promise se demoró un tiempo en ejecutarse.
    	Si se desea que la ejecución resulte en órden, se debería incluír el último console.log() dentro de la función pasada a .then(), de esta manera
    		solo se verá el mensaje de fin cuando la promesa se ejecute correctamente, ej:
    		let promesa = new Promise( (resolve, rejected) => {
    			setTimeout( () => {
    				resolve("Éxito");		// Esta promesa al ser ejecutada se resolverá exitosamente devolviendo el string "Éxito".
    			}, 2000);					// La promesa tardará 2 segundos en resolverse.
    		})
    		console.log("Ejecución de la promise...");
    		promesa.then( msg => {
    			console.log("Mensaje devuelto por la promesa: ", msg);
    			console.log("Fin de la ejecución de la promise.");
    		})
    
    En caso de querer contemplar el caso en el que la promesa por alguna razón falla durante su ejecución, se debe agregar la llamada a .cacth() y
    	pasarle la funcionalidad a ejecutarse en tal caso, ej:
    
    	let promesa = new Promise( (resolve, rejected) => {
    		setTimeout( () => {
    			rejected("La promesa falló!");		// Esta promesa al ser ejecutada se resolverá como Rechazada.
    		}, 2000);								// La promesa tardará 2 segundos en resolverse.
    	})
    	console.log("Ejecución de la promise...");
    	promesa.then( msg => {
    		console.log("Mensaje devuelto por la promesa: ", msg);
    	}).catch( err => {
    		console.log("Este mensaje se mostrará cuando la ejecución falle:", err);
    	})
    	console.log("Fin de la ejecución de la promise.");
    El resultado por consola de esta ejecución es el siguiente:
    	Ejecución de la promise...
    	Fin de la ejecución de la promise.
    	Este mensaje se mostrará cuando la ejecución falle: La promesa falló!
    
  1. Utilización de valores retorno de Fetch

    https://developer.mozilla.org/es/docs/Web/API/Fetch_API/Utilizando_Fetch https://developer.mozilla.org/es/docs/Web/API/Body

    fetch es un método global de Javascript que devuelve una Promise, pero esa promise todavía no tiene el resultado que se espera. fetch toma como parámetro la url a la que se desea hacer la solicitud, este parámetro es obligatorio. fetch devuelve entonces una Promise que finalmente se resuelve a un objeto Response, de ese response de puede consultar su objeto body (https://developer.mozilla.org/es/docs/Web/API/Body) y ejecutar métodos que él mismo provee para convertir la respuesta obtenida en algo que nos resulte útil, por ejemplo ".json()". .json() es un método que se ejecuta sobre el objeto Response y luego de leerlo hasta el final devuelve una Promise que se resuelve con el resultado de parsear todo el contenido del body a JSON.

  1. Transformación de datos

    Análisis del json obtenido desde el servidor para planificar como extraer desde el mismo la información relevante que el componente que muestra los datos del clima necesita para funcionar correctamente.

  1. Arquitectura de datos: independencia de API

    En este punto se desarrolla una función que obtiene como parámentro la respuesta desde el servidor y devuelve un objeto cuyo contenido es precisamente lo que el componente WeatherLocation necesita para mostrarse correctamente.

    Esto permite tener una interfaz de usuario independiente de la tecnología subyacente en el servidor al que se le solicitan los datos, permitiendo por ejemplo que si algún día se cambia de servidor del clima, tocando solamente esa funcionalidad se pueda seguir haciendo que el componente reciba los datos correctos (configurando nuevamente el mapeo hecho ahí dentro).

  1. Object Literal Property Value Shorthand

    https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Operators/Object_initializer

  1. Convert-Units

    Una opción de hacer que la temperatura se vea en grados centígrados, es agregar a la url del servidor al que se piden los datos, el siguiente parámetro: &units=metric por lo que quedaría así: const api_weather = ${url_base_weather}?q=${location}&appid=${api_key}&units=metric; y todos los valores se obtendrán en grados centígrados.

    Otra opción es usar por ejemplo la librería 'convert-units', lo que permite desarrollar una funcionalidad que le permita al usuario elegir en todo momento en que notación desea ver los valores de las temperaturas.

    Instalación:
    	npm install convert-units
    
    Uso:
    	import convert from 'convert-units';
    	getCelsius = kelvin =>		// Creo un método que recibe un valor en kelvin
    		Number(					// y lo devuelve convertido en Celsius, con sólo dos decimales.
    		convert(kelvin)
    			.from("K")
    			.to("C")
    			.toFixed(2)
    		);
    
  1. Services Layer

    SOLID: -> S: Single responsability

    	Quiere decir que cada una de las clases tienen que tener una única responsabilidad para poder tener el menor nivel de acoplamiento,
    		lo que permite que luego se modifique lo más rápido posible cuando se necesite hacerlo, sin que esto afecte a otras clases.
    
    	Teniendo en cuenta esto, se hace incapié en que la clase WeatherLocation posee métodos que hacen transfomaciones de los datos (getData,
    		getTemp, getWeatherState...) y esto está mal porque se está acoplando la vista con tales funciones de transformación.
    		Esto es mejor sacarlo de esta clase y hacer lo que se llama una "capa de servicios" que exponga estas funcionalidades, para de paso
    			reutilizarlas desde otro lado si fuese necesario.
    		Para esto, se crea una carpeta en el raíz llamada "services" con el archivo "transformWeather.js"
    			Este archivo contendrá una constante con cada uno de los métodos de la clase (se quitán por lo tanto de la clase) y se cambia
    			el nombre del método getWeatherState a transformWeather y se lo exporta con export default transformWeather;
    			En la clase, importa este archivo y se en el click del botón ahora se llama a esta función en lugar de a this.getWeatherState().
    
    	También se transladan las constantes utilizadas para formar la url del servicio del clima al archivo "constants/api_url.js" y se importa
    		la constante api_weather que es la única que utilizará el WeatherLocation.
    
  1. React Class Component LifeCycle

    Eventos del ciclo de vida de los componentes de clase de React

    Los eventos que se ejecutan son los siguientes: constructor componentWillMount componentDidMount componentWillUpdate componentDidUpdate render

    El orden en el que se ejecutan, la primera vez que se carga el componente, es el siguiente:

    constructor
    componentWillMount			UNSAFE		Se va a discontinuar, se debería usar componentDidMount	**
    render
    componentDidMount			** Este es el lugar correcto donde se deberían hacer solicitudes al servidor.
    

    Cada vez que se actualiza el componente, se ejecutan los siguientes:

    componentWillUpdate			UNSAFE		Se va a discontinuar, se debería usar componentDidUpdate **
    render
    componentDidUpdate
    
  1. ComponentDidMount y Network Slow 3G Chrome Tool

    Teniendo en cuenta de que no se puede utilizar el método componentWillMount() porque será discontinuado, se debe tener en cuenta de que siempre sucederá que la primera vez que el componente se renderice y muestre lo hará sin datos del servidor, por lo que hay que preparar el componente para que muestre datos que den a entender al usuario de que el componente aún se está cargando y no posee la información final. Luego de prepararlo con un estado incial, se debe agregar la funcionalidad que obtiene los datos reales en el método componentDidMount() Por lo que el componente se renderizará incialmente dos veces, una en la carga incial y otra en la actualización cuando se obtengan los datos del servidor.

  1. Indicador de Carga, utilización ternario

    Uso del operador ternario

  1. Material Design

    Explicación general sobre Material Design https://material.io/

  1. Material UI

    https://material-ui.com/es/

    Componentes de React para un desarrollo web más rápido y sencillo.

    Instalación: https://material-ui.com/es/getting-started/installation/ npm install @material-ui/core

    Los componentes de Material-UI funcionan sin ninguna configuración adicional, y no ensucian el global scope: import React from 'react'; import { Button } from '@material-ui/core';

    	function App() {
    		return <Button color="primary">Hello World</Button>;
    	}
    

    peerDependencies - https://classic.yarnpkg.com/es-ES/docs/dependency-types/ Las dependencias en pares son un tipo especial de dependencia que solo se necesitan si estás publicando tu paquete. Al tener una dependencia en par, significa que tu paquete necesita una dependencia que es exactamente la misma dependencia que la persona que instala tu paquete. Esto es útil para paquetes como react que necesita tener una única copia de react-dom que también es usada por la persona que instala tu paquete.

    Material-UI fue diseñado con la fuente Roboto en mente. Así que asegúrate de seguir estas instrucciones: https://material-ui.com/es/components/typography/#general The Roboto font will not be automatically loaded by Material-UI. The developer is responsible for loading all fonts used in their application. Roboto Font has a few easy ways to get started. For more advanced configuration, check out the theme customization section: https://material-ui.com/es/customization/typography/ Puedes referenciarla, por ejemplo, a través de Google Web Fonts:

  1. Instalación y uso de MaterialUI

    Instalación: yarn add @material-ui/core

    Agregado de la fuente Roboto a public/index.html:

    Agregado del meta viewport requerido para que todo lo relacionado con Material-UI se vea bien en celulares:

  1. Utilización y configuración de ESLint

    http://eslint.org

    Un Linter permite un cheque estático del código.
    Eslint se busca e instala como extensión de VSCode, la versión actual es la 2.1.2
    Puede facilitar la utilización normas de estilo (uso de mayúsculas, minúsculas al escribir el código, el uso de espacios o tabs, comillas simples o dobles, lineas con o sin punto y coma al final, etc.)
    Las aplicaciones creadas con Create-React-App ya posee una configuración establecida por defecto en el archivo package.json, la misma se escuentra en la sección "eslintConfig":

    "eslintConfig": {
        "extends": "react-app"
    },

    "react-app" hace referencia a un conjunto de reglas preestablecidas y conocidas por Eslint y al instalar la extensión para VSCode las mismas comienzan a ser verificadas a medida que escribimos código.

    Como VSCode tiraba un error en la ventana de Salida que decía que no podía ejecutar Eslint, lo investigué y solucioné creando el archivo ".vscode/settings.json", según indican en esta página:
    vuejs/eslint-plugin-vue#976 (comment)
    en el archivo establecí la ruta a la carpeta con mi código js:

    {
        "eslint.workingDirectories": ["./weather-app/src"]
    }

    Luego inicialicé eslint en el directorio de trabajo ejecutando lo siguiente:

    .\node_modules\.bin\eslint --init
    

    Esto me pidió que elija que configuraciones deseaba utilizar y luego de instalar paquetes extra necesarios, creó el archivo ".eslintrc.json" y comenzó a marcar correctamente en la ventana de "Problemas" los errores detectados en el código.
    Como no dejaba de marcarme como error en las funciones arrow (en el signo =), lo investigué y encontré que la solución era agregar esto:

    "parser": "babel-eslint",

    https://grantnorwood.com/eslint-parsing-error-unexpected-token-visual-studio-code/

  1. Uso de propiedades en Class Component combinado con state
  1. LocationList

    Creación de componente que tiene una lista de componentes WeatherLocation

  1. Mapeo de estados a íconos

    Refactor para utilizar correctamente el dato al respecto del estado del clima en cada ciudad y mostrar el ícono correspondiente en consecuencia.

  1. Agregamos parámetros a LocationList

    Me adelanté y probé de usar map para generar componentes WeatherLocation en base a ítems recibidos en el array de ciudades

  1. Refactorización de LocationList

    Uso de map para generar componentes WeatherLocation en base a ítems recibidos en el array de ciudades

  1. ES6: Función de collections Map

    Explicación de uso de Map

  1. Uso de Key en listas de componentes

    Explicación de por qué React necesita que cada componente de una lista tenga un valor único en su atributo Key y no es recomendado el uso del índice que el componente pueda tener en dicha lista (array).
    Al utilizar el índice, puede suceder que el array se modifique, agregando o eliminando un componente del mismo, lo que haría que todos pasen a tener otro índice, por lo tanto React debe volver a renderizarlos a todos para actualizar dicho valor.
    En cambio, más correcto sería utilizar un id único que cada entrada del array pudiera tener, o como en este caso en que el array es de ciudades, es mas inteligente utilizar el nombre de ciudad como Key, ya que no tendría sentido que haya una ciudad repetida, por lo que cada una cumpliría con tener una Key única (el nombre) y al agregar nuevas o quitar alguna, React podría eficientemente notar las diferencias y eliminar las que ya no están en el array del DOM y agregar las nuevas entre o al inicio o fin de las existentes.

  1. Estilos de comunicación de componentes: Eventos, Routing y Estado global

    Explicación de las formas en que un componente puede comunicar a otros componentes acciones o sucesos producidos.

  1. "Burbujeo" de eventos

    Realización de un "burbujeo" del evento click, desde el componente WeatherLocation hacía el componente padre App.

  1. Repaso de los eventos creados y salida por consola
  1. NOTA SOBRE ACTUALIZACIÓN
  1. MediaQueries, Flexbox, Bootstrap

    Explicación general sobre MediaQueries, Flexbox, Bootstrap, ReactBootstrap y React Flexbox Grid

    https://developer.mozilla.org/es/docs/CSS/Media_queries

    Las media queries (en español "consultas de medios") son útiles cuando deseas modificar tu página web o aplicación en función del tipo de dispositivo (como una impresora o una pantalla) o de características y parámetros específicos (como la resolución de la pantalla o el ancho del viewport del navegador).

    Se utilizan para:

    • Aplicar estilos condicionales con las reglas-at @media e @import de CSS.
    • Indicar medios específicos en los elementos , y otros elementos HTML.
    • Testear y monitorizar los estados de los medios usando los métodos de javascript Window.matchMedia() y MediaQueryList.addListener().

    https://developer.mozilla.org/es/docs/Web/CSS/CSS_Flexible_Box_Layout/Conceptos_Basicos_de_Flexbox

    El Módulo de Caja Flexible, comúnmente llamado flexbox, fue diseñado como un modelo unidimensional de layout, y como un método que pueda ayudar a distribuir el espacio entre los ítems de una interfaz y mejorar las capacidades de alineación.

    https://es.wikipedia.org/wiki/Bootstrap_(framework)

    Bootstrap es una biblioteca multiplataforma o conjunto de herramientas de código abierto para diseño de sitios y aplicaciones web. Contiene plantillas de diseño con tipografía, formularios, botones, cuadros, menús de navegación y otros elementos de diseño basado en HTML y CSS, así como extensiones de JavaScript adicionales. A diferencia de muchos frameworks web, solo se ocupa del desarrollo front-end.

    https://reactstrap.github.io/

    This library contains React Bootstrap 4 components that favor composition and control. The library does not depend on jQuery or Bootstrap javascript. Ejemplo: https://codesandbox.io/s/optimistic-sea-kpqdj?file=/src/App.js

    http://roylee0704.github.io/react-flexbox-grid/ https://github.com/roylee0704/react-flexbox-grid

    react-flexbox-grid is a set of React components that implement flexboxgrid.css.
    It even has an optional support for CSS Modules with some extra configuration.

  1. React Flexbox: Autosize, Alignment, Distribution

    Video que continúa explicando algo que asume que se mostró en un video anterior, aunque no es así y no queda del todo claro.

  1. Herramienta en Chrome para testear diseño responsivo

    Utilización de las herramientas de desarrollador de Chrome para seleccionar distintos dispositivos para la representación de la aplicación (desde la barra superior que hace aparecer Chrome cuando se muestran las herramientas de desarrollador)

  1. Uso de Grid, Row, Col y vh

    Instalación de React Flexbox

    yarn add react-flexbox-grid
    

    Uso de componentes Grid, Row, Col

    Utilizando Grid, establezco que todo el contenido se ubicará dentro de una grilla, a la cual se le incluirá el contenido a mostrar utilizando los componentes Row y Col. Ejemplo:

    <Grid>
        <Row>Fila 1 (por defecto usará todo el ancho de la pantalla)</Row>
        <Row>
            <Col xs={12} md={6}>
                Fila 2 - Columna 1 (en pantalla chica ocupará todo el ancho, en pantallas medianas o grandes ocupará media pantalla nada más)
            </Col>
            <Col xs={12} md={6}>
                Fila 2 - Columna 2 (en pantalla chica ocupará todo el ancho, en pantallas medianas o grandes ocupará media
                pantalla nada más)
            </Col>
        </Row>
    </Grid>

    Configuración de cantidad de columnas que se desea utilizar en cada tamaño de pantalla:

    Donde: Cuando la pantalla tenga un tamaño considerado xs (small), esta columna ocupará las 12 columnas de ancho, o sea, el contenido ocupará todo el ancho de la pantalla. Cuando la pantalla tenga un tamaño md (medium), esta columna ocupará solo 6 columnas, o sea, la mitad de la pantalla. Y si hay luego otra fila con una columna configurada igual, quedarán una al lado de la otra.

GitHub Pages:

Me propuse hacer que la app pueda ser accedida online desde GitHub Pages, para lo cual hice lo siguiente:

  • Leí la documentaciónde GitHub Pages y en consecuencia actualicé el archivo package.json, agregando esta línea:
        "homepage": "https://jonatandb.github.io/CursoUdemyReactJSReduxES6/",
  • Creé la carpeta "docs" y copié adentro todos los archivos generados al ejecutar:

            yarn build
    
    • Esto generó una versión optimizada para producción de la aplicación en la carpeta "build"
  • Fui a la sección de Settings del repositorio y en la parte de GitHub Pages, seleccioné desde el combo "Source" "master branch /docs folder"

  • Subí el código y la página ya está disponible públicamente desde la siguiente URL:

      https://jonatandb.github.io/CursoUdemyReactJSReduxES6/
    
  • A partir de ahora, cada vez que quiero subir una nueva versión debo hacer lo siguiente:

      1 - Dentro de "weather-app" ejecutar:
              yarn build
      2 - Borrar todo el contenido de la carpeta "docs"
      3 - Copiar el contenido de la carpeta "build" dentro de la carpeta "docs":
              Meterme en la carpeta "docs" y ejecutar:
                  xcopy /EFHK ..\weather-app\build .			(O usar el explorador de Windows)
      4 - Hacer commit y push
    

Eslint:

Leyendo la documentación de VSCode, volví a revisar el tema de Eslint que no me estaba sugiriendo un estilo de escritura de código, y noté que faltaba especificar, al incializar Eslint (mediante la ejecución de: eslint --init), seleccionar la opción "To check syntax, find problems, and enforce code style", que permite definir el estilo de escritura de código para el proyecto.

Por lo que elegí "Airbnb" e instalé los paquetes extra que me sugirió que instalara:

  • eslint-plugin-react@^7.19.0
  • eslint-config-airbnb@latest
  • eslint@^5.16.0 || ^6.8.0
  • eslint-plugin-import@^2.20.1
  • eslint-plugin-jsx-a11y@^6.2.3
  • eslint-plugin-react-hooks@^2.5.0 || ^1.7.0

Apenas terminó de instalar esos paquetes, VSCode empezó a indicar con color rojo los archivos con cosas a revisar y en la ventana de "PROBLEMAS" apareció el número 146 :-)

Los problemas principales encontrados fueron los siguientes:

  • string envueltos en comillas dobles
    • Como estoy usando Prettier, lo configuré para que haga esto cuando se graba el archivo, agregando lo siguiente al archivo ".vscode/settings.json":
      "prettier.singleQuote": true
  • lineas terminando en CRLF
    • Como no quiero usar finales de lína de Unix (LF), configuré Eslint para que ignore esto agregando lo siguiente al archivo ".eslintrc.json":
      "linebreak-style":"off"
  • funciones flecha con saltos de línea
    • Configuré Prettier para especificarle que las línes tienen un ancho máximo de 120 caracteres para que no agregue saltos de línea automáticos cortando en dos o más las líneas anchas con funciones flecha. Agregué lo siguiente al archivo ".vscode/settings.json":
      "prettier.printWidth": 120
  • sentencias console.log
    • Configuré Eslint para que marque solo como advertencias las ocurrencias que encuentre de llamadas a console.log en el código agregando lo siguiente al archivo ".eslintrc.json":
      "no-console":"warn"

  1. MaterialUI AppBar

    Agregado de una barra de navegación de Material:

    • Paper: Contenedor que puede tener un realce para que tenga sombra
    • AppBar: Barra de navegación
      • Position="sticky", hace que permanezca arriba de la página.
    • Toolbar:
    • Typography: Permite mostrar distintos tamaños de tipografías, ideal para el título
  2. CSS Mejoras

    Se hacen ajustes en las hojas de estilo para mejorar el aspecto de varios componentes.

    Se establece un valor de 4 a la propiedad "elevation" del componente Paper para que el mismo aparezca realzado mediane una sombra que da la impresión de estar elevado, despegado del fondo.

  3. Diseño Responsivo avanzado: Media Query

    En base a MediaQuery se detecta el tamaño de la pantalla y se aplican estilos CSS en consecuencia.

    Para que MediaQuery pueda actuar, debe estar configurado, en "index.html", el meta tag "viewport" con el valor "width=device-width" en su atributo "content":

        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
  4. Plan de componente ForecastExtended

  5. Creación de ForecastExtended

    También volví a investigar sobre Eslint, Prettier y las reglas de Airbnb, llegando a estos sitios:

    Esto permitió que elimine todo lo relacionado a eslint y a prettier del archivo "settings.json" y que instale como dependencias de desarrollo los siguientes paquetes:

    • yarn add -D eslint-config-airbnb eslint-plugin-jsx-a11y eslint-plugin-import eslint-plugin-react babel-eslint
    • yarn add -D eslint prettier
    • yarn add -D eslint-config-prettier eslint-plugin-prettier

    Al finalizar estas instalaciones quedó todo perfectamente configurado, ahora cuando escribo código y grabo, Prettier formatea el archivo respetando las reglas de estilo impuestas por Eslint según lo recomendado por Airbnb :-)

  6. Creación de parámetro para ForecastExtended

  7. Utilización de state en App.js

  8. Actualización de state

  9. Ciclo de actualización de state / render

    Repaso del ciclo de vida de los componentes de React y cuando se re-renderizan y cuando no.

  10. Manejo de estado inicial

    Utilización del operador ternario para realizar un renderizado condicional cuando aún no se ha seleccionado ninguna ciudad.

  11. Manejo de estado inicial 2

    Renderizado condicional utilizando el operador lógico AND (doble ampersand): &&

  12. Truthy values y Falsy values

    Truthy
    https://developer.mozilla.org/es/docs/Glossary/Truthy
    En JavaScript, un valor verdadero es un valor que se considera true/verdadero cuando es evaluado en un contexto Booleano. Todos los valores son verdaderos a menos que se definan como falso (es decir, excepto false, 0, -0, 0n, "", null, undefined, y NaN).

    Falsy
    https://developer.mozilla.org/es/docs/Glossary/Falsy
    Un valor falso (a veces escrito falsey) es un valor que se considera falso cuando se encuentra en un contexto booleano. JavaScript utiliza la conversión de tipos para forzar cualquier valor a un valor booleano en contextos que lo requieren, como condicionales y bucles.

    Juego de Tabla de Igualdad de JavaScript
    https://eqeq.js.org/#es

  13. Estilo ForecastExtended: Utilización de ClassName

  14. Presentación del componente ForecastItem

  15. Creación componente ForecastItem

  16. Utilización de array de componentes

  17. Incorporación de WeatherData al ForecastItem

  18. Planificación de Fetch contra servidor

    Explicación de por qué se utilizará el componentDidMount y no componentWillMount

  19. Primer paso de refactorización de ForecastExtended: Indicador carga inicial

  20. Api OpenWeatherMap para pronostico extendido: Forecast

    Explicación de uso de la api de OpenWeatherMap para obtener datos del pronóstico de los próximos 5 días.

  21. Ejecución de Fetch Forecast

    Se utiliza fetch aunque se explica que también se podría utilizar axios, ya que tiene soporte para navegadores antiguos.

  22. Creación de servicio de transformación

  23. Plan de transformación de datos

  24. Moment.Js

    Explicación general de la librería Moment.JS

    https://momentjs.com/

  25. Utilización de filter

    Uso de funciones unix() y utc() de momentjs para filtrar los pronósticos para los siguientes 5 días obtenidos del servidor y generar una lista con solo 3 pronósticos para cada día, para ciertas horas especificas.

  26. Uso de Map, y Culturización con Moment Locale

    Importación de 'moment/locale/es' para que los días de la semana en texto devueltos por moment aparezcan en español

    Agrego validación en el método componentDidUpdate() del componente ForecastExtended para que cuando se clickea en una nueva ciudad se haga una nueva solicitud del pronóstico extendido al servidor de OpenWeatherMap

  27. Generación de ForecastItems en base a los datos

  28. Mejora visual

    Creo componente personalizado pare reemplazar el CircularProgress de MaterialUI

    Páginas consultadas:

  29. Ciclo de vida de React: ComponentWillReceiveProps

    Refactor a componente ForecastExtended para que recargue el pronóstico extendido cuando se actualiza la propiedad city mediante el uso del método de ciclo de vida de React "ComponentWillReceiveProps".

    Al utilizar el método ComponentWillReceiveProps obtuve una alerta en la consola debido a que React desaconseja su uso debido a que será discontinuado:

       Warning: componentWillReceiveProps has been renamed, and is not recommended for use. See https://fb.me/react-unsafe-component-lifecycles for details.
    
       * Move data fetching code or side effects to componentDidUpdate.
       * If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://fb.me/react-derived-state
       * Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. In React 17.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.
    

    Investigando al respecto dí con esta página que explica como solucionar problemas asociados al uso de éste método y al hecho mismo de necesitar utilizarlo, cosa que se da en raros casos:

    • https://es.reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops

        Nota:
      
        El uso de este método de ciclo de vida a menudo conduce a errores e inconsistencias
      
        Si necesitas realizar un efecto secundario (por ejemplo, obtención de datos o animaciones) en una respuesta debido a un cambio en los props, utiliza componentDidUpdate.
      
        Si usaste componentWillReceiveProps para re-calcular algunos datos cuando un prop cambie, utiliza memoization.
      
        Si quieres restablecer algún state cuando un prop cambie considera hacer un completamente controlado o un componente no controlado con una key/clave.
      
        Para otros casos de uso, sigue las recomendaciones en este blog sobre estado derivado:
        - https://es.reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html
      

    En el nuevo ciclo de vida de componentes de React se agregó el método estático: getDerivedStateFromProps:

    Updating state based on props:

       "As of version 16.3, the recommended way to update state in response to props changes is with the new static getDerivedStateFromProps lifecycle.
       It is called when a component is created and each time it re-renders due to changes to props or state"
    

    "React ensures that any setState calls that happen during componentDidMount and componentDidUpdate are flushed before the user sees the updated UI."

    React 16.12

       React will _not_ call the deprecated lifecycle methods:
           componentWillMount
           componentWillUpdate
           componentWillReceiveProps
       if any of the new lifecycle methods are present:
           getDerivedStateFromProps    static
           getDerivedStateFromError    static
           getSnapshotBeforeUpdate
    

    Gráfico interactivo del ciclo de vida de los componentes:

    Fases del ciclo de vida de un componente:

    • https://es.reactjs.org/docs/react-component.html#the-component-lifecycle

      Montaje:

      • Se ejecuta siempre y solo lo hace una vez
      • Contruye el componente con su estado inicial
      • Obtiene las props
      • Primera ejecución del método render
      • Termina con el componente montado en el DOM
      • Orden de los métodos que se ejecutan durante el montaje:
        • constructor(props)

          • https://es.reactjs.org/docs/react-component.html#constructor
            • Si no inicializas el estado y no enlazas los métodos, no necesitas implementar un constructor para tu componente React.

            • El constructor para un componente React es llamado antes de ser montado. Al implementar el constructor para una subclase React.Component, deberías llamar a super(props) antes que cualquier otra instrucción. De otra forma, this.props no estará definido en el constructor, lo que puede ocasionar errores.

            • Normalmente, los constructores de React sólo se utilizan para dos propósitos:

              • Para inicializar un estado local asignando un objeto al this.state.
              • Para enlazar manejadores de eventos a una instancia.
            • No debes llamar setState() en el constructor(). En su lugar, si su componente necesita usar el estado local, asigna directamente el estado inicial al this.state en el constructor:

                  constructor(props) {
                      super(props);
                      // No llames this.setState() aquí!
                      this.state = { counter: 0 };
                      this.handleClick = this.handleClick.bind(this);
                  }
              
              • El constructor es el único lugar donde debes asignar this.state directamente.
                • En todos los demás métodos, debes usar this.setState() en su lugar.
              • Evita introducir cualquier efecto secundario o suscripciones en el constructor.
                • Para estos casos de uso, use componentDidMount() en su lugar.
              • Nota
        • static getDerivedStateFromProps(props, state)

        • componentWillMount() (DEPRECADO), se podría utilizar su variante: UNSAFE_componentWillMount() (AUN NO DEPRECADO)

        • render()

          • https://es.reactjs.org/docs/react-component.html#render
            • El único método que obligatoriamente debe existir en nuestro componente para que este pueda funcionar
            • Retorna los elementos que queremos mostrar en la página, también puede devolver arrays, string, números... también puede devolver null, lo que significa que no debe renderizarse nada.
            • Este método debe ser siempre puro, esto es, que NO modifique el state del componente y que no interactúe con nada del navegador, ya que provocaría un loop infinito. Para esas cosas hay otros métodos disponibles.
            • Por lo tanto se debe encargar solo y simplemente de, utilizando las props y el state, generar una representación visual en la aplicación.
            • Evitar operaciones y transformaciones en este método, ya que penalizará a la performance de la aplicación.
        • componentDidMount()

          • https://es.reactjs.org/docs/react-component.html#componentdidmount
            • Se ejecuta tras renderizar el componente
            • Se ejecuta una sola vez y justo después del primer render()
            • Ya tendremos una representación en el DOM del mismo
            • Se puede utilizar setState()
            • Es el lugar correcto para hacer llamadas a servicios externos (por ej. usando fetch()), obtener datos y actualizar el state con ellos
            • También podemos suscribirnos a eventos del navegador como por ejemplo el scroll que se hace en la página y si lo hacemos tenemos que borrar esta suscripción en el método componentWillUnmount(), que se ejecutará antes de desmontar el componente.

      Actualización:

      • El ciclo de actualización estará activo desde que se monta el componente hasta que se desmonta
      • En este ciclo además de actualizar lo que nuestro componente ha renderizado también podremos indicar si el renderizado es necesario
      • Una actualización puede ser causada por cambios en los props o el estado.
      • Estos métodos se llaman en el siguiente orden cuando un componente se vuelve a renderizar:

      Desmontaje:

      • componentWillUnmount()
        • https://es.reactjs.org/docs/react-component.html#componentwillunmount
          • Este método es llamado cuando un componente se elimina del DOM:
          • Realiza las tareas de limpieza necesarias en este método, como la invalidación de temporizadores, la cancelación de solicitudes de red o la eliminación de las suscripciones que se crearon en componentDidMount().
          • No debes llamar setState() en componentWillUnmount() porque el componente nunca será vuelto a renderizar.

      Manejo de errores:

      • https://es.reactjs.org/docs/react-component.html#error-handling
      • Estos métodos se invocan cuando hay un error durante la renderización, en un método en el ciclo de vida o en el constructor de cualquier componente hijo.
        • static getDerivedStateFromError(error)
          • https://es.reactjs.org/docs/react-component.html#static-getderivedstatefromerror
            • Este ciclo de vida se invoca después de que un error haya sido lanzado por un componente descendiente. Recibe el error que fue lanzado como parámetro y debe devolver un valor para actualizar el estado.
            • Nota:
              • getDerivedStateFromError() se llama durante la fase “render”, por lo que los efectos secundarios no están permitidos. Para estos casos de uso, use componentDidMount() en su lugar.
        • componentDidCatch(error, info)
          • https://es.reactjs.org/docs/react-component.html#componentdidcatch
            • Este ciclo de vida se invoca después de que un error haya sido lanzado por un componente descendiente.
            • componentDidCatch() se llama durante la fase “commit”, por lo tanto, los efectos secundarios se permiten.
            • Nota:
              • En el evento de un error, puedes renderizar una interfaz de usuario con componentDidCatch() llamando a setState(), pero esto estará obsoleto en una futura versión. Usa static getDerivedStateFromError() para controlar el plan de renderizado.
      • Introduciendo Límites de Errores
        • https://es.reactjs.org/docs/error-boundaries.html
        • Los límites de errores son componentes de React que capturan errores de JavaScript en cualquier parte de su árbol de componentes hijo, registran esos errores, y muestran una interfaz de repuesto en lugar del árbol de componentes que ha fallado.
        • Los límites de errores capturan errores durante el renderizado, en métodos del ciclo de vida, y en constructores de todo el árbol bajo ellos.
        • Nota:
          • Los límites de errores no capturan errores de:
            • Manejadores de eventos (aprende más)
            • Código asíncrono (p.ej. callbacks de setTimeout o requestAnimationFrame)
            • Renderizado en el servidor
            • Errores lanzados en el propio límite de errores (en lugar de en sus hijos)
        • Un componente de clase (class component) se convierte en límite de errores si define uno (o ambos) de los métodos del ciclo de vida:
          • static getDerivedStateFromError()
            • Usa static getDerivedStateFromError() para renderizar una interfaz de repuesto cuando se lance un error.
          • o componentDidCatch().
            • Usa componentDidCatch() para registrar información de los errores.

    Algunos refactors recomendados:

  30. Revisamos lo que vimos

  • Enumerado de tecnologías utilizadas hasta ahora:
    • VSCode
    • VSCode Plugins
    • NPM
    • Yarn
    • NODE
    • HTML/HTML5
    • CSS/CSS3
    • ECMAScript5/6
      • Map
      • Filter
      • Template strings
      • Promises
      • Fetch
    • Herramientas de debugging de Chrome
    • Herramientas de debugging de VSCode
    • React
      • Functional Components
      • Class Components
      • Ciclo de vida de los componentes
      • PropTypes
      • Keys
    • Librerías varias
      • ConvertUnits
      • Material UI
      • FlexboxGrid
      • ReactWeatherIcons
      • Moment
  1. Ciclo de Vida React 16
  • Fases del ciclo de vida
    • Montaje
      • Constructor
      • Render
      • ComponentDidMount
    • Actualización
      • Render
      • ComponentDidUpdate
    • Desmontaje
      • ComponentWillUnmount
    • Manejo de Error
      • Solo se ejecutará en caso de que se produzca algún problema durante el renderizado de un componente, en algunos de los métodos del ciclo de vida o en el constructor.
  • Métodos deprecados
    • ComponentWillMount
    • ComponentWillUpdate
    • ComponentWillReceiveProps
  1. ¿Qué hace que un componente se actualice?
  • Cuando se ejecuta setState() y por lo tanto se actualiza el estado del componente

  • Cuando llegan nuevas props recibidas desde el componente padre

  • Cuando se llama al método forceUpdate()

    ¿Que elementos se pueden renderizar?

    • React elements (Componentes nativos y componentes de usuario, extendidos de React.Component) JSX
    • Strings, números

    Ciclo de Vida React 16.4

    • Fases del ciclo de vida
      • Montaje
        • Constructor
        • getDerivedStateFromProps
        • Render
        • ComponentDidMount
      • Actualización
        • getDerivedStateFromProps
        • shouldComponentUpdate
        • Render
        • getSnapshotBeforeUpdate
        • ComponentDidUpdate
      • Desmontaje
        • ComponentWillUnmount
  1. Virtual DOM
  • DOM (Document Object Model)
    • Representación visual, mantenida por el navegador, de los elementos que componen una pagina web

      • Mantiene una jerarquia de objetos HTML que el navegador puede representar
      • Cada vez existe alguna modificación en este DOM, se generan modificaciones visuales en la página
      • Alterar el DOM es una tarea que lleva tiempo y no es performante, a menos que se realice de una manera muy selectiva.
    • React logra el objetivo de realizar modificaciones muy selectivas de una manera muy performante gracias a la utilización del Virtual DOM:

      • Es una representación en memoria liviana de cada elemento generado y ante una modificación en los mismos realiza una comparación para detectar los cambios que existieron y finalmente impacta solo estos cambios en el DOM real, con lo que evita actualizaciones innecesarias y hace este proceso tan eficiente como podría ser.
  1. One Way Data Flow
  • Funcionamiento del Virtual DOM
    • OneWay Dataflow
      • El flujo de datos dentro de la jerarquía de React se mueve en una sola dirección, en sentido descendente, la información pasa de componentes padres a componentes hijos por medio de las props, por esto se le llama OneWay Dataflow.
    • El virtual DOM es una representación liviana en memoria de los componentes, en forma de árbol
    • Proceso de Reconciliation de React:
      • Los componentes están en un estado incialmente formando una estructura de árbol y en base a ese estado, que incluye las propiedades y ciertos datos más, React crea el virtual DOM asociado a ese árbol
      • Luego React genera el DOM real durante el montado del componente, lo que permite verlo en la página
      • Luego mediante algún evento, como puede ser un click o cualquier otro tipo de cambio, se genera un cambio de estado uno o más componentes
      • El cambio de estado genera un nuevo DOM virtual asociado pero con alguna modificación en la rama o hoja del árbol que fue modificada
      • React realiza comparaciones y detecta que hay diferencias entre las dos versiones del DOM virtual y finalmente actualiza el DOM real modificando sólo la parte que cambió.
        • Con esto se obtiene una eficiencia muy alta ya que no se modifican partes del DOM real que no hayan sufrido cambios.
  1. Proceso de Reconciliation
  • Para que el árbol del DOM virtual pueda ser generado y comparado correctamente, React tiene reglas al respecto del mismo:
    • Dos elementos o nodos de diferentes tipos producirán árboles diferentes.
    • Cuando existieran elementos hijos del mismo tipo, el desarrollador puede proveer una clave (key) para indicar cuáles elementos permanecen estables entre diferentes renderizaciones.
  • Mecanismo de diffing (Cómo React detecta un cambio):
    • Primer caso -> Se cambió el tipo de elemento dentro de una rama del árbol
      • Si por ejemplo se cambió un div por un span, entonces se asume que se cambió toda la rama que estuviera por debajo de ese cambio. En ese caso se desmontará el componente anterior mediante "componentWillUnmount" y se montará el nuevo con "componentWillMount".
        • El estado del componente anterior al cambio se perderá por completo.
    • Segundo caso -> Actualización del componente
      • Cuando React compara elementos del mismo tipo se fija en los atributos y sólo actualiza los atributos que hayan cambiado (por ejemplo a div se le cambió el className)
      • Luego sigue la comparación sobre los elementos hijos.
      • A diferencia del primer caso, en la actualización de un componente de un mismo tipo se mantiene el estado y sólo se invoca el evento "componentWillUpdate".
    • Tercer caso -> Comparación de elementos hijos
      • Se produce este proceso de comparación cuando el elemento padre es el mismo, pero se actualizó.
      • Por ejemplo podría tratarse de un div o cualquier otro componenten que contenga otros componentes. Entonces React va iterando recursivamente sobre el árbol de componentes hijos y compara por posición el componente hijo anterior a la modificación y posterior, generando los cambios necesarios cada vez que encuentra diferencias entre los valores de sus propiedades.
  • Detalle de comparación realizada por React durante el mecanismo de reconciliation para los componentes hijos:
    • Por ejemplo al modificar una lista como la siguiente:

      <ul>
          <li>Primero</li>
          <li>Segundo</li>
      </ul>
      

      agregándole un elemento como sigue:

      <ul>
          <li>Primero</li>
          <li>Segundo</li>
          <li>Tercero</li>
      </ul>
      

      React va a comparar la nueva versión del primer elemento y no va a encontrar diferencias, por lo que pasará a comparar el segundo, para el cual tampoco encontrará diferencias y detectará que se ha agregado el tercero, por lo que lo insertará en el DOM.

    • Un caso no tan sencillo:

      <ul>
          <li>Río de Janeiro</li>
          <li>Cusco</li>
      </ul>
      

      agregándole un elemento al principio:

      <ul>
          <li>San José</li>
          <li>Río de Janeiro</li>
          <li>Cusco</li>
      </ul>
      

      En este caso React va a encontrar diferencias en todas las posiciones (ya que Río no está más en la primera posición, así como tampoco Cusco en la segunda) por lo que las actualizará e insertará un nuevo elemento llamado Cusco al final de la lista.

      • En este caso el cambio no se realizó de la mejor manera y es muy inficiente.
      • Podríamos notar la sobrecarga en el proceso durante la actualización de listas largas con gran cantidad de ítems.

      Solución:

      • Parte del segundo principio de la heurística de comparación del mecanismo de reconciliation requiere que se utilice una clave (key) en los componentes que forman parte de una lista.

      • Teniendo en cuenta esto, ahora se agregan a los elementos una key:

        <ul>
            <li key="2010">Río de Janeiro</li>
            <li key="2011">Cusco</li>
        </ul>
        

        y luego del agregado de un nuevo elemento la lista quedará así:

        <ul>
            <li key="2012">San José</li>
            <li key="2010">Río de Janeiro</li>
            <li key="2011">Cusco</li>
        </ul>
        

        Ahora React buscará difenrencias en los elementos teniendo en cuenta las claves, por lo que detectará que debe agregar solamente el elemento con clave 2012 -> San José.

        • Es muy importante que las claves no sean aleatorias o random, ya que de esa manera la heurística funcionaría de una manera poco eficiente debido a que entre cada renderizado todas las claves cambiarían.
        • Tampoco se debería utilizar como clave el índice del elemento en la lista de la que proviene, ya que si se agregan o quitan elementos de la lista todos los índices cambiarían y de nuevo el proceso de reconciliation tendría mucho trabajo que realizar comparando todo por completo nuevamente, lo que incluso podría provocar algunos fallos.
        • Para que una clave sea buena y permita un buen rendimiento:
          • Debe permanecer estable entre renderizaciones.
          • Podría ser una propiedad de los datos que vamos a mostrar.
  1. Reconciliation en acción
  • Explicación gráfica del proceso de comparación de nodos del árbol del DOM virtual durante el proceso de reconciliation de React.

  • React Fiber: nombre del nuevo motor de evaluación del DOM virtual que lleva a cabo el proceso de reconciliation.

    • Es retrocompatible con las versiones anteriores, por lo que se puede actualizar la versión de React de nuestras aplicaciones sin necesidad de llevar a cabo ningún tipo de cambio para aprovechar las bondades del nuevo motor optimizado.
    • Realiza un renderizado incremental mucho mas eficiente solamente en los momentos que se necesita de acuerdo a las modificaciones programadas para realizarce.
  1. SPA vs MPA
  • Comparación entre SPA (Single Page Application, aplicaciones de una sola página) y MPA (Multiple Page Application, aplicación de múltiples páginas) que en general están construídas utilizando la arquitectura MVC.

    • MPA:

      • Ya sea por acceder a la página (request a una url en el navegador) o mediante una acción, como un click, se genera una solicitud que viaja al servidor, en el servidor se resuelve, se genera un HTML (la página a mostrar en consecuencia), se envía de vuelta al navegador y termina siendo representada por el DOM, por lo que tenemos la representación visual de la respuesta a disposición con la cual podemos interactuar, consultar, etc.
      • Al volver a hacer click o solicitar otra página, se vuelve a llevar a cabo todo este proceso (también se podría hacer una solicitud concreta de información mediante AJAX)
      • Si bien hay algunas alternativas para hacer este proceso más óptimo, en general es el mismo:
        • El navegador solicita una página al servidor
        • El servidor lleva a cabo los procesamientos de datos que fueran necesarios
        • Genera el HTML, que viaja por la red
        • Vemos el HTML en el navegador.
      • Siempre se produce este traspaso de información y es bastante perceptible cuando se cambia de página porque se actualiza la misma completamente.
      • Entre los frameworks más comunes que trabajan con MVC están:
        • ASP NET MVC
        • Laravel
        • CodeIgniter
    • SPA:

      • Trabaja de manera diferente:
        • En la primer solicitud, se obtiene del servidor:
          • El HTML, que es muy liviano
          • Un paquete "bundle" de Javascript, que contiene toda la definición de la aplicación
            • Este bundle de Javascript tiene la capacidad de ir generando todas las páginas que vaya solicitando el usuario a medida que interactúa con la misma, incluso puede manipular la url que se ve en el navegador para que el comportamiento de la página se perciba exactamente igual que cuando se intereactúa con un sitio clásico (MPA) pero con la ventaja de que se cambia de página sin la necesidad de recargar la página por lo tanto no hay que ir a buscar HTML nuevo al servidor.
              • El único momento en que se va a consultar al servidor es cuando se necesite una respuesta de datos, ya no va a estar viajando HTML desde el servidor al navegador.
              • El servidor posee entonces una interfaz API con la que la aplicación interactúa mediante solicitudes generalmente en formato JSON.
              • En base a la respuesta del servidor, la apliación puede volver a renderizarse, pero siempre sin recargar la página, lo que brinda:
                • Una muy buena experiencia para el usuario
                • Una velocidad mayor perceptible durante la navegación de las páginas del sitio que componen los distintos módulos del mismo
        • El manejo del routing, o el renderizado del lado del servidor se resuelven de una manera fácil.
        • Permiten mejorar el SEO de la página.
        • Permiten mejorar la carga inicial.
        • El único posible problema aún es el tamaño del bundle que puede ser potencialmente grande.
      • Los frameworks más comunes para trabajar con SPA son:
        • React
        • Barebone
        • Angular
    • SPA: Recomendable para aplicaciones web, sitios que deben soportar múltiples consultas al día, dando respuesta en el menor tiempo posible.

    • MPA: Está bien para sitios que aunque sean visitados por muchos usuarios, no sean utilizados durante una larga interacción, sino que más bien provea unas cuantas páginas que los usuarios dejen de utilizar luego de relativamente una escasa cantidad de consultas.


Nota sobre Strict Mode:

  • El StrictMode fuerza a todos los componentes a renderizarse dos veces y sirve para poder poner a prueba nuestra aplicación. Con ese procedimiento y varios chequeos más, permite descubrir algunos problemas o puntos mejorables, por ejemplo, adaptación a las últimas versiones de React.

  1. Redux
  • Framework para manejar el estado de la aplicación
  • El estado es único y global para toda la aplicación
    • Redux denomina al estado: "Store"
  • La única forma de manipular el estado es mediante "actions"
    • Cada vez que una "action" influye sobre el estado, lo que hace es generar una nueva versión del mismo basada en el versión anterior.
      • Nunca se modifica el estado, siempre se genera una nueva versión basada en la anterior pero con alguna modificación.
  1. Instalación de Redux, React-Redux y React Dev Tools Plugin
  • yarn add redux

    • https://redux.js.org/
      • Actions - https://redux.js.org/basics/actions
        • Las acciones son cargas de información que envían datos desde su aplicación a su Store.
        • Son la única fuente de información para el Store.
        • Las envía al Store usando store.dispatch ().
        • Action Creators - https://redux.js.org/basics/actions#action-creators
          • Los creadores de acciones son exactamente eso: funciones que crean acciones. Es fácil combinar los términos "acción" y "creador de acción", así que haz lo posible por usar el término apropiado.
      • Reducers - https://redux.js.org/basics/reducers
        • Los reductores especifican cómo cambia el estado de la aplicación en respuesta a las acciones enviadas al Store. Recuerde que las acciones solo describen lo que sucedió, pero no describen cómo cambia el estado de la aplicación.
      • Store - https://redux.js.org/basics/store
        • En las secciones anteriores, definimos las acciones, que representan los hechos sobre "lo que sucedió" y los reductores que actualizan el estado de acuerdo con esas acciones.
        • El Store es el objeto que los une y tiene las siguientes responsabilidades:
          • Mantiene el estado de la aplicación
          • Permite el acceso al estado a través de getState()
          • Permite que el estado se actualice mediante dispatch(acción)
          • Registra oyentes (listeners) a través de subscribe(listener)
          • Maneja el des-registrado de los listeners a través de la función devuelta por subscribe(listener)
      • Data Flow
        • https://redux.js.org/basics/data-flow
          • La arquitectura de Redux gira en torno a un flujo de datos unidireccional estricto.
          • Esto significa que todos los datos en una aplicación siguen el mismo patrón de ciclo de vida, haciendo que la lógica de su aplicación sea más predecible y más fácil de entender.
          • También fomenta la normalización de datos, para que no termines con copias múltiples e independientes de los mismos datos que no son conscientes entre sí.
          • El ciclo de vida de los datos en cualquier aplicación Redux sigue estos 4 pasos:
            • Llamada a store.dispatch(action)
            • El Store de Redux llama a la función reductora que le corresponde a esa acción
            • El reductor raíz puede combinar la salida de múltiples reductores en un solo árbol de estado
            • El Store de Redux guarda el árbol de estado completo devuelto por el reductor raíz.
  • yarn add react-redux

  • Instalación de Redux DevTools

  1. Creación de store, dispatch de acciones y uso de React Dev Tools
  • Se crea un store vacío, con un reducer que no hace nada, pero se hace dispatch de una acción básica para verificar el correcto funcionamiento de la extensión de Redux DevTools desde Chrome, para poder verificar el state a medida que se producen cambios en el mismo por medio del dispatch de actions mientras se utiliza la aplicación.

  • Como indica la documentación de la extensión, para que la misma pueda vincularse al store de la aplicación y dar información sobre lo que sucede con el mismo, al momento de crear el store mediante el uso de la función createStore() de Redux, se debe agregar luego del o los reducers que se deseen utilizar, lo siguiente:

        // Redux, creación del store:
        const store = createStore(
            () => {}, /*Reducer o reducers que se harán cargo de las actions pasadas a store.dispatch()*/
            window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
        );
    
  1. Generación de action creator
  • Creación de un action creator que permite que quede más explícito que tipo de acción se envía al store.
    • Es simplemente una función que recibe como parámetro una ciudad y devuelve un objeto JSON que respeta la forma de un action
      • Posee una propiedad type, con el valor 'setCity'
      • y una propiedad value, con la ciudad recibida por parámetro
  1. Mejora a action creator
  • Refactors:
    • Creación de carpeta 'actions', con action creator exportado para luego importarlo y utilizarlo desde 'App.jsx'.
    • Creación y exportación de constante SET_CITY, para futura utilización desde los reducers.
  1. Refactorización de Store y vinculación de Provider
  • Se envuelve al componente App con el componente Provider para que pueda acceder al store luego de las configuraciones pertinentes.
  1. Connect
  • Uso de connect() para permitirle al componente App acceder al store
    • Mediante la función mapDispatchToProps lo que se hace es decirle a connect() que inyecte al componente App una propiedad llamada dispatchSetCity, la cual al ser ejecutada (mediante la llamda a this.props.dispatchSetCity()), realiza una llamada a dispatch() (función que connect() pasa como parámetro a mapDispatchToProps) pasándole como parámetro el resultado de llamar a setCityActionCreator() con la ciudad clickeada como parámetro (lo que devuelve una action con la ciudad como value) y ésta action generada entonces es pasada a dispatch().
      • Entonces:
        • Al envolver a App con connect():
          • Se le pasa a connect() como segundo parámetro una función que connect() va a usar para inyectar una propiedad a App: mapDispatchToProps(), entonces se inyecta la propiedad --> dispatchSetCity, que es una función.
          • Esta función inyectada (yo la llamé dispatchSetCity(), pero puede tener cualquier nombre) recibe de parte de connect() la función dispatch() del store, por lo que puede despachar acciones, ejecutando dispatch(acción).
          • Una vez que App tiene esta propiedad disponible, al utilizarla se la llama con la ciudad seleccionada como parámetro --> this.props.dispatchSetCity(ciudad)
            • Esta ciudad, dentro de dispatchSetCity(), se pasa primero a setCityActionCreator(), lo que devuevle un action con la ciudad como value y el type 'SET_CITY'.
            • Finalmente la acción se pasa a dispatch(acción), entonces el store detecta la acción y se la pasa al reducer correspondiente para que haga el trabajo que se deba realizar cuando llega una acción de este tipo.
  • Como connect() devuelve como resultado una nueva función que recibe como parámetro el componente que se desea "conectar" al store, se crea una nueva constante llamada AppConnected
    • Que va a ser el componente App pero con acceso al store (inicialmente solamente mediante la nueva propiedad dispatchSetCity())
      • Por lo tanto es éste el componente devuelto en el export de App.js:
        • export default AppConnected;
  1. ¿Función que retorna funciones?

  2. Connect en detalle - https://www.udemy.com/course/react-js-redux-es6-completo-de-0-a-experto-espanol/learn/lecture/8951404

  • Según entiendo, entonces connect() recibe dos funciones, a la primera le pasa como parámetro el state y a la segunda le pasa como parámentro la función dispatch()

    • Espera que la primer función devuleva un objeto, el cual va a tener asociado como valor a cada propiedad una parte específica del state
    • Espera que la segunda función también devuelva un objeto, el cual va a tener asociado como valor a cada propiedad una función, ésta nueva función por dentro llamará a dispatch() y le pasará el resultado de llamar a un action creator con el parámetro recibido.
  • Finalmente, connect(mapStateToProps, mapDispatchToProps)(ComponenteAConectar) lo que hará será llamar al componente pasándole como parámetro el resultado de unificar los dos objetos devueltos por las funciones recibidas una vez ejecutadas (mapStateToProps y mapDispatchToProps). Así el componente 'conectado' podrá acceder por medio de 'this.props' a todas las propiedades que acceden a valores del state y a las que permiten enviar actions al store (las que por dentro llaman a dispatch()).

  • Mi práctica en CodePen replicando la funcionalidad de connect() para comprenderlo completamente :-)

  1. Validación de funciones inyectadas por DispatchToProps
  • Agregado de propTypes para que se valide que dispatchSetCity sea una función
  • Exportación directa del resultado de llamar a connect() para no generar un constante innecesaria (AppConnected)
  1. Containers vs Presentational Components
  • Smart components = Container components -> "Componentes inteligentes"

    • Componentes que tienen acceso al estado de la aplicación
      • Están vinculados a éste gracias connect().
      • No tienen representación visual.
    • Recomendaciones:
      • Que los containers sean componentes de "alto nivel", que no estén muy profundamente anidados en la jerarquía de componentes
        • En este caso, componentes candidatos para ser containers serían:
          • LocationList
          • ForecastExtended
      • Intentar tener una cantidad reducida de containers en la aplicación.
  • Dumb components = Presentational components -> "Componentes tontos"

    • Solo se encargan de renderizar algo en pantalla, solo tienen lógica de presentación
  • Cuanto más clara se haga la separación entre componentes containers y presentacionales, más claro será el manejo del estado de la aplicación, ya que se podrá restrear como se está manipulando el estado mirando tan sólo los containers existentes en la misma.

  1. Creación de container LocationListContainer
  • Creación de container LocationListContainer en base al componente LocationList
  • Refactor al componente App para que utilice el nuevo container
  1. Creación de Reducer
  • Creación de reducer: cityReducer
    • Actualiza la propiedad city del state cada vez que detecta que se hizo dispatch de la acción 'SET_CITY'.
  • Refactor del store para que reciba el reducer cityReducer y un state inicial por defecto.
  1. Entendiendo el reducer

  2. Pure Functions

  • Uno de los conceptos básicos de los reducers, es que deben ser "funciones puras"
    • Función pura:
      • Funcíón que depende solo de los parámetros que recibe, su retorno depende solo de los valores recibidos.
        • No depende de ningún estado de la aplicación
        • No depende de un acceso a una base de datos
        • No depende de la respuesta de una solicitud http
        • No depende de ningún otro tipo de valor externo, más allá de los que recibe
      • Esto la torna una función predecible, sin sorpresas
      • Algo más a tener en cuenta es que no debe alterar los valores que le llegan por parámetro
        • De esta manera no genera efectos colaterales: "side effects"
    • En el caso de los reducers, a la hora de devolver un nuevo estado, nunca deben modificar el estado recibido
      • Deben crear y retornar un nuevo objeto en base al objeto state recibido
        • Esto significa que nunca se debería hacer algo como esto:

            state.prop = 'Nuevo valor';
            return state;
          
        • Lo anterior se debe evitar, por ejemplo utilizando el spread operator:

            return { ...state, prop: 'Nuevo valor' };
          
          • Nota: También se podría utilizar Object.assign().

          De esta manera se crea y retorna un nuevo objeto, el cual es una copia del objeto state, pero que tiene agregada (o si ya existía, entonces actualizaría) la propiedad 'prop'.

  1. Container responde a MapStateToProps
  • Creación de componente container ForecastExtendedContainer, que a diferencia de LocationListContainer que se conectaba al store para luego enviarle acciones, se conecta al store para leer la propiedad city del state y finalmente inyectarsela al componente ForecastExtended para que éste obtenga los datos del servidor en base a la ciudad que fue seleccionada.
  1. Repasando MapStateToProps y MapDispatchToProps

  2. Middlwares de Redux

  • Explicación sobre qué son y la utilidad de los middlewares:
    • Son funcionalidades que se agregan al store cuando este se configura inicialmente y que son interpuestas entre el dispatch() y la llegada de la acción a los reducers, lo que permite agregar capacidades extra al Store.
      • Estas funciones intermediarias pueden tener funcionalidades muy variadas, como por ejemplo loguear las acciones que se fueron ejecutando, atender eventos asincrónicos (como lo hace por ejemplo redux-thunk), capturar errores, cambiar rutas y muchas cosas más.
  1. Incorporación de middleware Thunk
  • Instalación:

    yarn add redux-thunk
    
  • Para poder especificar middlewares durante la creación del store, se debe utilizar la función de Redux: applyMiddleware.

  • Para poder seguir utilizando el plugin de Chrome Redux DevTools, se debe utilizar también la función de Redux: compose.

  1. Redux-Thunk desde adentro
  • Entonces, según entiendo, lo que el middleware thunk hace es interceptar la action que fue pasada a dispatch() y antes de pasarla a los reducers chequea si la misma es una función:
    • Si detecta que la action es una función entonces la ejecuta pasándole como parámetro la función dispatch.
      • Está action de tipo función entonces al ser ejecutada, hará el trabajo que tenga que realizar y podrá ejecutar dispatch() ya que lo recibió por parámetro y puede que le pase finalmente un objeto con un type como las demás actions o que incluso pase otra función que nuevamente el middleware thunk recibirá y ejecutará.
    • Si detecta que la action es otra cosa diferente de una función, entonces ejecuta dispatch pasandoselá como parámetro para que siga su curso normal hacía los reducers.
  1. Planeamos: Nuevo estado de aplicación
  • Se plantea nueva estructura del estado de la aplicación que por un lado seguirá teniendo información de la ciudad seleccionada y por otro contendrá una lista de ciudades junto con sus datos de pronóstico cargados a medida que cada ciudad sea seleccionada.
    • De esta manera, si se vuelve a seleccionar una ciudad para la que ya se habían obtenido los datos del pronóstico extendido, no se realizará una nueva solicitud al servidor, sino que se utilizarán y mostrarán los datos para esa ciudad previamente almacenados en el state.
  1. Refactor action setCity
  • Modificación de la llamada a dispatch en el componente LocationListContainer para que cuando se seleccione una ciudad se le pase como parámetro la nueva función fetchForecastData() en lugar de la action setCity.
    • Esta función es detectada por el middleware thunk y ejecutada (con la función dispatch como parámetro)
      • Al ejecutarse, primero hace un dispatch de la acción que establece la ciudad seleccionada (SET_CITY)
        • Luego hace el fetch al servidor para obtener asíncronamente los datos del pronóstico extendido
          • Finalmente, al recibir los datos, hace un nuevo dispatch de una nueva action con el type: SET_FORECAST_DATA, a la que le pasa como payload los datos obtenidos del servidor.
            • Aún no se ha creado un reducer que contemple esta action.
  1. Creación de reducer cities
  • Creación de reducer para contemplar la action 'SET_FORECAST_DATA', que impacta en el store la información del pronóstico extendido para la ciudad seleccionada.
  • Hago refactor cambiando varios nombres (de los reducers, de las acciones y la propiedad city del state), para una mejor legibilidad y más fácil seguimiento del código y manipulación del state.
  1. Utilización de combineReducers
  • https://redux.js.org/api/combinereducers
  • combineReducers es una función provista por Redux, la cual lo que hace es recibir varios reducer y devolver un único objeto donde cada propiedad del mismo posee el nombre de cada reducer recibido (esto puede ser modificado en caso de que se desee) y como valor de cada propiedad se encuentra cada reducer.
  1. Simplificación de class component a functional component

  2. Selectores primer nivel

  • Los selectores "recortan" una parte del estado global de la aplicación, permitiendo que se pueda trabajar con esa parte del estado exclusivamente desde los componentes.
  • Permite evitar que un componente tenga conocimiento de la estructura del estado de la aplicación y por lo tanto lo desacopla de la misma, por lo que al modificar/refactorizar el estado no hace falta modificar el componente.
  • Los selectores es conveniente crearlos en los reducers, ya que es donde se conoce la estructura del estado de la aplicación.
  • Una de las librerías mas conocidas que implementan y proveen el patrón selector es 'Reselect'.
  1. Selectores, completo
  • Refactor para abstraer por completo el conocimiento que el componente tiene sobre el estado de la aplicación
    • Para lograrlo se va a crear una nueva función en index de reducers que va a recibir el state como parámetro (cuando sea llamada desde el container) y va a devolver el resultado de llamar al selector previamente creado y al que se importó con un alias y se le pasó como parámetros las partes del state que específicamente necesita para funcionar -> la ciudad seleccionada y el array de ciudades.
  • Creación de nuevo selector para obtener la ciudad seleccionada desde el componente ForecastExtendedContainer
  1. Reselect
  • https://github.com/reduxjs/reselect

  • Instalación y uso de Reselect

    yarn add reselect
    
  • Reselect utiliza la técnica memoization, que implementando una cache liviana permite el trabajo mucho mas eficiente cuando se manejan grandes volúmenes de datos

  • Una vez importada la función createSelector de Reselect, se utiliza pasándole una o más funciones, las cuales ejecutará pasándole a cada una el state y el dato obtenido de cada una será pasado a la última función recibida.

    import { createSelector} from 'reselect'
    export const getCity = createSelector(state => state.city, city => city)
    
    • createSelector recibe el state y se lo pasa la primera función especificada, la cual devuelve city y este resultado es pasado a la última función especificada, que recibe city y devuelve city.
  • https://medium.com/@pearlmcphee/selectors-react-redux-reselect-9ab984688dd4

  1. Memoization y fortalezas de los selectores
  • Son eficientes, ya no se ejecutan si ninguno de sus parámetros se modifica (comparándolos con la llamada anterior).
  • Permiten composición: nuevos selectores pueden tomar como entrada otros selectores.
  • Pueden minimizar el tamaño del store, ya que permiten generar datos procesados 'al vuelo', en vez de tener que guardarlos.
  • Su implementación, internamente lo que hace es:
    • Compara si son iguales los argunmentos recibidos contra los argumentos de la ejecución anterior
      • En caso de que sean iguales:
        • Recordará los argumentos actuales como los últimos recibidos durante la próxima ejecución
        • Devolverá el resultado que tenía almacenado en la ejecución anterior
      • En caso de que no sean iguales:
        • Guardará como útlimo resultado lo que devuelva la ejecución de la función recibida por parámetro aplicada a los argumentos pasados al selector
        • Recordará los argumentos actuales como los últimos recibidos durante la próxima ejecución
        • Devolverá el resultado que tenía almacenó como último resultado (el de la ejecución de la función)
  • Implementación de memoization de Reselect:
  1. Refactor de componente con state a functional component
  • Primera parte de refactor de componentes WeatherLocation, LocationList y LocationListContainer
  1. Creación de Action Creators
  • Segunda parte del refactor de componentes, creación de action "setWeather" para obtener los datos del clima para cada una de las ciudades.
  1. Creación de Reducer
  • Armado de reducer para actualizar el estado al iniciarse la petición de datos del clima para una ciudad y al obtenerse el resultado de la petición.
  1. Selector
  • Preparación incial del componente LocationListContainer para que obtenga del state el resultado del clima para las ciudades.
  1. Lodash
  1. Utilización de toPairs (entries)
  • Instalación y uso de lodash.topairs para pasarle al componente LocationListContainer refactorizado los datos en el formato que los necesita.
  1. toPairs en detalle
  • Explicación de funcionalidad y uso de toPairs
  1. Uso de spread operator para realizar copia en segundo nivel

  2. Establecer Forecast desde en carga inicial

  3. BindActionCreators

  4. Uso de segundo parámetro getState en redux-thunk

  5. Redux, Flux y SSOT

  6. Presentación de temas

  7. Wireframes de la aplicación CustomersABM

  8. Creación de la aplicación y primeros componentes

  9. Código fuente

  1. Componente CustomerData

  2. Componente CustomerActions

  3. Componente Link

  • Permite el manejo dinámico de la url, sin recargar la página

  • Tiene la misma apariencia que un link habitual

  • Instalación de react-router-dom (paquete de npm que provee el componente Link y el componente BrowserRouter, entre otros):

    yarn add react-router-dom

  1. CustomerListItem

  2. CustomersList

  3. CustomerEdit dummy

  4. Estructura de navegación

  5. Utilización de Route

  6. Utilización de Switch

  7. HomeContainer e implementación con Link

  8. Utilización de history.push y withRouter

  • Envolviendo un componente con withRouter, se consigue que se le inyecten al mismo las propiedades location, match y history de react-router-dom. Con estas propiedades disponibles se puede utilizar por ejemplo history.push() como resultado de un click en un botón para cambiar la url y llevar al usuario a otra "pagina", de la misma forma que lo hace el componente Link:

    this.props.history.push("/customers");

  1. Customer Container

  2. WithRouter y navegación a eliminar

  • Agregado de withRouter al componente CustomersContainer
  1. React Router v4, dynamic router y más
  • React-router-dom y React-router-native comparten el core de react-router

    • Para la web se utilizar React-router-dom
  • Dentro de los componentes que administran el ruteo, está el componente Router como componente de alto nivel y base, indistinto de la forma en que se realiza el ruteo.

  • Luego hay tres implementaciones diferentes de Router:

    • BrowserRouter:
      • La mas utilizada
      • Se apoya en funcionalidades de HTML5 que permiten modificar la URL (usando la API History).
      • Es el utilizado para sincronizar las URL solicitadas con la URL del navegador.
    • HashRouter:
      • Utiliza el numeral en la URL
      • No recomendado por poseer ciertas incompatibilidades en casos conocidos clave
    • MemoryRouter:
      • No modificar la URL
      • Se utiliza especialmente para testing en react-router-dom o en React Native (ya que es una plataforma que no soporta el manejo de URL)
  • Parámetros que aceptar BrowserRouter:

    • basename: Permite que se especifique cual es la ruta base, en base a la cual luego se construye el arbol del resto de rutas.
    • forceRefresh: Especialmente diseñado para navegadores viejos que no soportan en forma completa HTML5. Al establecerlo en true provoca un refresco completo de la página al cambiar de URL.
    • getUserConfirmation: Recibe una función opcional, que sirve para llevar a cabo una validación y mostrarsela al usuario para que confirme la navegación. Por defecto no se ejecuta validación que solicite confirmación al usuario.
  • Route:

    • Es el componente más importante.

    • Cuando el valor de "location" (window.location) se corresponde con el valor de la propiedad "path", Route renderiza el o los componentes visuales que se le hayan especificado:

      <Route path="/customers" .../>

    • Hay tres formas de asociar componentes a Route:

      <Route path="/customers" component={Customers} />

      <Route path="/customers" render={ () => ( <Customers/> ) />

      <Route path="/customers" children={ ({match, ...rest}) => (match ? <p>Si</p> : <p>No</> )} />

  1. Route, match, switch, history y más
  • Atributos de Route:

    • exact:
      • Si la ruta no coincide exactamente con la que está especificada en el atributo "path" no se va a renderizar el componente asociado. Por lo tanto si en path se especifica '/customers' y la URL es "/customers/new", sin exact el componente asociado se renderizará. Con exact, solo se renderizará cuando la URL se exactamente "/customers".
    • strict:
      • Es similar a exact pero con respecto a si la URL posee o no una barra al final -> "/customers" no lo toma igual que "/customers/"
  • match:

    • Contiene información sobre wildcards (también llamados "url params") que se encuentren en la URL.
    • También posee información sobre:
      • Los wildcars -> match.params
      • Si la url es "exact" -> match.isExact
      • Cual fue el "path" utilizado para evaluar la ruta -> match.path
      • Porción de la ruta que coincidió con la evaluación -> match.url
  • :

    • Se utiliza con rutas que pueden presentar coincidencias ambiguas.

    • Totas las rutas dentro de Switch serán evaluadas en el orden que se encuentren, y se renderizará el componente de la primera que presente una coincidencia con el valor establecido en "path", ignorándose el resto (dejando de buscarse coincidencias).

    • Ejemplo:

      <Switch>

      <Route path="/customers/new" component={CustomerNewContainer} />

      <Route path="/customers/:dni" component={CustomerContainer} />

      </Switch>

      • En este caso, cuando se navegue a "/customers/new" se renderizará el componente CustomerNewContainer, pero si en lugar de "new" se especifíca cualquier otra cosa, Switch descartará la ruta que apunta a "/new" (porque no coincide) y seguirá revisando las rutas disponibles. Al encontrarse con la ruta con el wildcard "/:dni" en el path, lo que sea que se haya escrito luego de "/customers/" se guardará en una propiedad disponible a través de "props.match.params.dni" dentro del componente "CustomerContainer", que será el que se renderizará.
  • Link, NavLink:

    • Componentes similares que permiten la navegación a través de la propiedad "to" para indicar hacía que URL debe ir el navegador.
    • NavLink posee más opciones de personalización
  • Redirect:

    • Sirve para hacer redirecciones
    • Ideal para utilizar cuando el usuario se encuentra en algún flujo de navegación al cual no tiene permitido acceder.
  • withRouter:

    • Es un High Order Component
    • Agrega al componente envuelto, las siguientes propiedades: (También re-renderiza el componente cuando estas propiedades cambian)
      • match
      • location
      • history:
        • Es mutable (Alterable)
        • Las funciones que lo modificación son:
          • push: Se utiliza para agregar una nueva entrada a history
          • replace: Se utiliza para modificar el útlimo elemento de la pila "history", reemplazandolo por otro
          • go(n): Permite desplazarse por el history "n" posiciones
          • goBack(): Vuelve al elemento anterior en la pila de navegación de history
          • goForward(): Desplaza la navegación al siguiente elemento en la navegación
          • block(): Cancela o evita la navegación. Evita que el usuario se pueda desplazar por las distintas URLs
  1. Pasos para crear fetchCustomers
  • Análisis de pasos a seguir y requerimientos para continuar con el desarrollo de la aplicación
  1. Creación de store y vinculación con provider
  • Instalación de redux (que provee "createStore") y de react-redux que provee el componente "Provider" con el cual se puede proveer del store a toda la aplicación y que también provee el componente "connect" con el cual se le inyectan propiedades a los componentes para que puedan hacer dispatch de acciones y estar al tanto de cambios en el state (mediante mapStateToProps y mapDispatchToProps).
  1. Redux-Actions
  • Paquete que tiene como objetivo generar un código más compacto y más claro, fácil de leer.
  • Pasos para utilizarlo:
    • Conectar plugin de redux para Chrome (para poder depurar el state desde Chrome)
    • Crear constants (para respetar las buenas prácticas y porque ayudan a evitar errores en los tipos de las acciones)
    • Instalación de Redux-Actions
    • Utilización:
      • Modificando el ActionCreator usado hasta ahora
      • Simplificando el MapDispatchToProps del componente HomeContainer
  1. Utilización de DefautlProps, HandleAction y HandleActions

Redux-actions -> handleAction:

  • Funcionalidad para manejar los reducers
  • Recibe el type de la acción y la función de transformación del reducer

Redux-actions -> handleActions:

  • Similar a handleAction pero recibe un objeto, en el cual cada propiedad es del type de una acción y el valor es un reducer que recibe el state y debe devolver el nuevo state para esa acción.
  1. createAction: payloadCreator
  1. Utilización de Selector
  • Creación de función selectora, que recibe el state y devuelve la parte del mismo que corresponde, en el caso del CustomerContainer -> devuelve los customers.
  1. Json-Server
  1. Middlware Redux-Promise
  • Cuando se utiliza promiseMiddleware de redux-promise, al hacerse dispatch de una acción que tiene como payload una promise, redux-promise detiene la propagación de la acción y solo le hace dispatch cuando se resuelve la promesa detectada, pasando como payload la respuesta en un nuevo dispatch de una acción con el type de la acción interceptada inicialmente.
  1. Api Get
  • Refactor para creación de carpeta llamada api que posee las urls y funciones necesarias para interactuar con la API
  1. Redux-Promise a fondo

  2. Creación de CustomerContainer

  3. Utilización de Route.render y paso de parámetros

  4. Utilización de segundo parámetro "Props" en MapStateToProps

  5. Refactor y utilización de reselect

  6. Ruteo dinámico y propiedad "children" de Route

  7. Spread Properties y Component Type en ejecución

  8. Forms en React vs Redux Forms

  1. Instalación de Redux Form, incorporación del reducer

  2. Utilización de Fields de Redux Form


Support me on Ko-fi