3

Creando una Isomorphic app con React, Express y ES6 - Parte 2

164Puntos

hace 5 años

En la primera entrega de este artículo aprendimos que las aplicaciones isomórficas son aquellas que nos permiten ejecutar el código JavaScript, que normalmente ejecutamos en el cliente, en el servidor. Además, entendimos cómo funcionan las Single Page Apps (SPA) y cuáles son sus beneficios. Para poner en práctica estos conceptos, iniciamos un desarrollo híbrido utilizando código JavaScript isomórfico para crear un Pokedex. En esta ocasión vamos a repasar el listado y buscador de Pokémons. Si te perdiste la primer parte de este artículo, te recomiendo empezar por ahí. Retomando el código de nuestra aplicación isomórfica inicial, comenzaremos con el paso 2: [js] $ git checkout paso2 “Lógica del cliente: Listar 151 Pokémons y filtrarlos” [/js] Primero debemos componetizar nuestra app de la siguiente manera: App Isomórfica React nos hace pensar en componentes. Esto es bueno, ya que así podemos ser más ordenados y reutilizar nuestro código. Abriremos el archivo pokeContainer.js que estará en el nivel más alto (“El padre”), y que contendrá los componentes: pokeList y pokeSearch (“Los hijos”). Además, cargaremos un JSON con toda la info de los Pokémons: [js] import React from 'react' import PokeList from './pokeList' import PokeSearch from './pokeSearch' import pokms from '../../public/pokemons.json' export default class PokeContainer extends React.Component{ constructor(props){ super(props) this.state = { inputValue:' ' } } searchBy(input){ this.setState({ inputValue : input.target.value }) } render(){ return <div> <h1>No esperes más! Encuentra toda la info sobre tu pokémon favorito.</h1> <PokeSearch searchBy={this.searchBy.bind(this)} /> <PokeList pokemons={pokms} inputValue={this.state.inputValue.toLowerCase()}/> </div> } } React.render(<PokeContainer />, document.getElementById('container')) [/js] En React tenemos principalmente dos propiedades: las Props y el State. El primero se caracteriza por ser immutable. Es decir, no debería cambiar. El segundo es lo contrario, se encarga de cambiar el estado de la aplicación. Cada vez que éste es actualizado, el método render() vuelve a ejecutarse y sucede que redibuja el componente y todos los hijos que tenga. Así que debemos evitarlo. En la jerarquía de componentes sólo debería cambiarse el state del componente de más alto nivel. En nuestro caso, esta es la razón por la que pokeContainer será el único que tenga un state. Una prop se define como atributo de un componente. Por otro lado, el state se define como una propiedad de la clase en el constructor. Aunque esto puede variar si no usamos JSX y ES6. ¿Y cómo los componentes de más bajo nivel podrán tener dinamismo? Tal como se ilustra en la línea 20. El state del padre se “encauza” por medio de las props de los hijos. De esta manera, los componentes de abajo pueden actualizarse. Ahora debemos definir el método searchBy, que se encargará de actualizar el state inputValue. A su vez, este será pasado en las props del componente PokeList. De esta manera, la función searchBy se bindea. Es decir, adquiere la referencia dentro de PokeContainer y se pasa por las props de PokeSearch. Luego, en nuestro archivo pokeSearch.js insertamos el siguiente código: [js] import React from 'react' export default class PokeSearch extends React.Component{ render(){ return <div className="Search"> <input type="text" placeholder="Buscar Pokémon" onChange={this.props.searchBy}/> <img src="images/search.png"/> </div> } } [/js] Aquí podemos ver cómo PokeSearch recibe en sus props a searchBy; que a la vez será enganchado al evento onChange y se ejecutará cada vez que se ingrese algo en el input. Ahora, si abrimos el archivo pokeList.js, podremos ver el siguiente código: [js] import React from 'react' import Pokemon from './pokemon' export default class PokeList extends React.Component{ render(){ return <div className="PokeList"> { this.props.pokemons.map( pokemon => { if(pokemon.name.search(this.props.inputValue) > -1) { return <Pokemon key={pokemon.id} pokemon={pokemon}/> } }) } </div> } } [/js] Aquí hacemos uso de la prop pokemons que contiene un array con toda la información de los Pokémons, el cual mapearemos para realizar una búsqueda con el método search() que devolverá el Pokémon que coincida con la prop inputValue. Inicialmente nos devolverá los 151 Pokémons; ya que definimos el state inputValue con un string vacío. Como seguro notaste, también importamos el componente Pokemon, al cual se le pasan por las props un key, que le será asignado a cada Pokémon como un identificador único. Esto nos sirve para que React haga un mejor manejo de estos componentes. Por lo general se asigna sólo cuando se hace una iteración en una lista de elementos. Además, le pasamos la prop pokemon, que contendrá el Pokémon que fue mapeado. Por último abriremos el archivo pokemon.js: [js] import React from 'react' const apiUrl = "http://img.pokemondb.net/sprites/black-white/anim/normal/" export default class Pokemon extends React.Component{ render(){ return <div className="Pokemon"> <figure> <a href={`/#pokemon/${this.props.pokemon.name}`}> <img src={`${apiUrl}${this.props.pokemon.name}.gif`} width="80"/> </a> </figure> <div> <span>{this.props.pokemon.id}</span> - {this.props.pokemon.name} </div> </div> } } [/js] Nuestro component Pokemon se conforma de un gif que traemos desde la API pokemondb. Por otra parte, con la ayuda del template strings (característica de ES6) y react, que nos permite usar expresiones Javascript, mostramos los datos de cada Pokémon de acuerdo a las props que nos llegan desde PokeList. Para ver a React en acción sólo nos queda realizar el build. De la mano de Browserify y Babelify, haremos el proceso de convertir nuestro código escrito en ES6 a código ES5 y guardarlo en el archivo public/js/build.js que será cargado y ejecutado por el navegador. Nos aseguramos de tener nuestras dependencias instaladas: [js] $ npm install [/js] Después ejecutamos el build: [js] $ npm run build [/js] Y finalmente lanzamos nuestro server con: [js] $ npm run server [/js] Abrimos nuestro navegador en localhost:8080, y observaremos la eficiencia con que React hace el render de los 151 Pokémons. Además, nos permite realizar la búsqueda por su nombre. Puedes ver el demo de este proyecto aquí. App Isomórfica En la siguiente y última parte de este artículo aprenderemos a manejar las rutas de la aplicación con el módulo react-router. Y terminaremos la vista del detalle de cada Pokémon. Este es sólo un pequeño adelanto de todo el potencial que tiene React.js, si quieres profundizar más en el tema, no te pierdas el Curso de React.js en Platzi. Ahí aprenderás todo sobre Single Page Apps, Realtime Apps y más.
David
David
@deivijt

164Puntos

hace 5 años

Todas sus entradas
Escribe tu comentario
+ 2