Skip to content

Instantly share code, notes, and snippets.

@hlrd93
Last active May 31, 2017 21:02
Show Gist options
  • Save hlrd93/a7223ba7ac640cf4867251adec2648ba to your computer and use it in GitHub Desktop.
Save hlrd93/a7223ba7ac640cf4867251adec2648ba to your computer and use it in GitHub Desktop.
React
#**React:** *First episode*
###*Introduction*
React is a Javascript library focused on the development of user interfaces. This is the main work area, but with the whole ecosystem of applications and tools and components, with React we find an excellent partner to make all kinds of web applications, **SPA (Single Page Application)** or even mobile applications.
It is therefore a base on which you can build almost anything with Javascript and that facilitates much development, as it offers us many things already ready, in which we do not need to invest time to develop.
###*Configurar React*
*React* es una librería de ***JavaScript*** para crear interfaces de usuario, el primer paso es configurar el entorno.
Hay dos maneras de configurar tu entorno para trabajar con *React*:
>1) Agregar los archivos de JavaScript necesarios.
2) Usar un manejador de paquetes como **NPM**, **jspm** o **bower**.
####*Agregar archivo en el HTML*
La manera más rápida para empezar a trabajar con *React* es usar los archivos *JS* que están públicos en *cloudflare.*
```javascript
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
</script>
</body>
</html>
```
Necesitamos dos archivos para poder trabajar con react: ***`react.js`*** y ***`react-dom.js`***.
Además también necesitamos agregar babel para que pueda transpilar el código en *jsx* a *JavaScript*.
####*Código JSX en archivo externo*
Es poco práctico tener el código de nuestros componentes en el documento HTML, es buena práctica tener el código en otro archivo.
```javascript
// helloword.js
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
```
Luego lo cargamos en el archivo html.
```javascript
<script type="text/babel" src="helloworld.js"></script>
```
####*Usar NPM*
Lo más recomendable es usar ***NPM*** y ***browserify***. Con *npm* podemos tener un archivo por componente y cargarlos usando require.
Creamos un archivo ***`main.js`*** y cargamos nuestras dependencias con require.
```javascript
// main.js
var React = require('react');
var ReactDOM = require('react-dom');
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
```
Es necesario también instalar las dependencias con *npm*:
```javascript
$ npm install --save react react-dom babelify babel-preset-react
```
Después corremos *browserify* sobre el *main.js*, este accederá a los archivos requeridos con require, transpilará el **JSX** a **JS**, y lo pondrá todo en un archivo.
```javascript
$ browserify -t [ babelify --presets [ react ] ] main.js -o bundle.js
```
Debes recordar tener instalado *browserify*.
####*NPM scripts*
Cada vez que actualizamos nuestro código es necesario correr el *browserify*, esto puede resultar tedioso escribir todo el comando. Afortunadamente con *npm* podemos crear scripts en nuestro proyecto que sirven como alias de estos comandos.
Para crear un script agregamos en nuestro archivo ***`package.json`*** en la sección de *scripts*:
```javascript
"scripts": {
"build": "browserify -t [ babelify --presets [ react ] ] main.js -o bundle.js"
}
```
Luego para correr el script solo hacemos:
```javascript
$ npm build
```
Podemos también crear un comando ***`watch`*** usando ***`watchify`***, de esta forma cada vez que cambie el archivo hace la transpilación a **JS** sin necesidad de tener que teclear *npm build* cada vez que cambiamos algo.
```javascript
"scripts": {
"build": "browserify -t [ babelify --presets [ react ] ] main.js -o bundle.js",
"watch": "watchify -t [ babelify --presets [ react ] ] main.js -o bundle.js"
}
```
Recuerda que tienes que tener instalado *watchify*.
####*Usar ES2015*
Podemos usar ES2015 o ES6 en nuestro código y transpilarlo a JavaScript, para eso necesitamos instalar otro paquete en nuestro proyecto llamado babel-preset-es2015.
```javascript
$ npm install babel-preset-es2015 --save
```
Y agregar el preset al browserify.
```javascript
$ browserify -t [ babelify --presets [ es2015 react ] ] main.js -o bundle.js
```
Y los npm scripts quedarían:
```javascript
"scripts": {
"build": "browserify -t [ babelify --presets [ es2015 react ] ] main.js -o bundle.js",
"watch": "watchify -t [ babelify --presets [ es2015 react ] ] main.js -o bundle.js"
}
```
####*What is React's goal?*
> - It serves to develop web applications in a more orderly and less code-oriented way, focused on manipulating the DOM.
> - Allows the views to be associated with the data, so that if the data changes, the views also change.
> - The spaguetti code produced by libraries like jQuery is intended to be architecturized and the way to get it is through components.
> - A user interface is basically created from a component, which encapsulates the operation and presentation.
> - Some components rely on others to solve more complex applications needs.
> - It allows to create other pieces of application comfortably, like the tests.
####*React es isomórfico*
Básicamente se trata de que, con un mismo código, se pueda renderizar **HTML** tanto en el *servidor* como en el *cliente*, rebajando la carga de trabajo necesaria para realizar aplicaciones web amigables para buscadores, logrando un buen posicionamiento.
####*Ecosistema de React*
Existe todo un ecosistema de herramientas, aplicaciones y librerías que al final equiparan React a un framework como el caso de ***Redux*** o ***Flux***, que aportan partes que React no se encarga, como el flujo de datos.
Al desarrollar en base a componentes reutilizables te permite usar el desarrollo de un proyecto en otro, hay componentes desde simples *botones*, *sliders*, *tooltips*, dichos componentes son capaces de trabajar de manera independiente y encapsular funcionalidades para que no interaccionen con otros componentes si no se desea.
***React Native*** es otra de las herramientas disponibles en el ecosistema, que permite llevar una aplicación escrita con *Javascript* y *React* como aplicación nativa para dispositivos ***iOS***, ***Android***, etc.
####*Lo que necesita saber sobre React en cinco conceptos clave*.
Los cinco conceptos clave de React son:
1. Componentes
2. JSX
3. Atrezzo y Estado
4. La Api de componentes
5. Tipos de componentes
####*Componentes*
Un componente *React* es un objeto único que no sólo produce la salida **HTML** como lo haría una plantilla tradicional, sino que también incluye todo el código necesario para controlar esa salida.
Un ejemplo perfecto de un componente común es el ***`<select>`***, elemento HTML. No sólo vienen con su propia salida visual sino que también se ocupa de su propia apertura y cierre de la lógica. Además puedes ser capaz de construir su propia aduana autónomo ***`<select>`***, con su propio estilo y comportamiento, esto es exactamente lo que permite hacer React.
####*Estructura y funcionamiento de un componente en React*
Un componente de *React* se puede crear de varias formas. Una de ellas es con el método ***`createClass`*** que ofrece la librería.
```javascript
const React = require('react')
const MyComponent = React.createClass({
...
})
```
Y la otra es utilizando las clases que ofrece **ECMAScript 6 (ES2015)**. En este caso heredan de la clase ***`Component`*** de *React* y necesitan llamar al constructor padre en el método constructor Si usamos ***Webpack*** con ***Babel*** podemos también usar el sistema de módulos de ***ES2015***:
```javascript
import React form 'react'
class MyComponent extends React.Component {
constructor () {
super()
}
...
}
```
####*Componentes funcionales*
Este tipo de componentes básicamente son funciones que reciben como parámetro las ***props*** y retorna un elemento. Pero una mejor manera de entenderlo es mostrándolo en código. Usando clases de *js* podemos definir un componente sencillo de la siguiente forma:
```javascript
class Greeting extends Component {
render() {
return (
<h1> Hello, {this.props.name}! </h1>;
}
}
```
Como puedes ver, el componente no contiene estado alguno. Solamente toma las ***props*** que le pasemos y nos retorna una representación en base a eso. Aun así, escribimos bastante código que no forma parte de la representación que deseamos. Por eso, es preferible mostrar este componente como un componente funcional.
```javascript
function Greeting(props) {
return <h1> Hola, {props.name}! </h1>;
}
// O si prefieres utilizar funcionalidades de es2015+:
const Greeting = ({ name }) =>
<h1> Hello, {name}! </h1>
;
```
Es bastante menos código que usando ***clases*** o ***React.createClass***, y también es más fácil de entender pues lo único que tenemos es el nombre del componente, las *props* y el elemento que regresamos.
####*Render*
Todo componente de *React*, tiene un método ***Render*** que es el que se encarga de renderizar en el navegador el **HTML** correspondiente al componente.
Este método se llama automáticamente cuando se crea un componente y cuando el estado del componente se actualiza.
En este método es donde usamos ***JSX*** para facilitar el desarrollo y creación de elementos **HTML**.
Veamos un ejemplo:
```javascript
import React from 'react'
class MyComponent extends React.Component {
constructor () {
super()
}
render () {
return (
<div>
<span>Hola!, soy un componente</span>
</div>
)
}
}
```
####*Propiedades*
Un componente en *React* puede recibir propiedades como parámetros desde un componente padre para poder insertar valores y eventos en su **HTML**.
Imagina que tienes un componente que representa un menú con varias opciones, y éstas opciones las pasamos por parámetros como una propiedad llamada options:
Veamos esto en código:
```javascript
import React from 'react'
class App extends React.Component {
constructor () {
super()
}
render () {
let menuOptions = ['Opción 1', 'Opción 2', 'Opción 3']
return <Menu options={menuOptions} />
}
}
```
¿Cómo accedemos a estas propiedades en el componente hijo a la hora de renderizarlo? Por medio de las *props*. Veamos como con el código del componente `<Menu />` :
```javascript
import React from 'react'
class Menu extends React.Component {
constructor (props) {
super(props)
}
render () {
let options = this.props.options
return (
<ul>
{options.map(option => <li>{option}</li>)}
</ul>
)
}
}
```
En el método render creamos una variable ***`options`*** con el valor que tenga ***`this.props.options`***. Éste ***`options`*** dentro de *props* es el mismo atributo *options* que tiene el componente ***`<Menu />`*** y es a través de *props* como le pasamos el valor desde el padre al componente hijo.
El código final de este ejemplo sería:
```javascript
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
constructor(props) {
super(props)
}
render() {
let menuOptions = ['Opción 1', 'Opción 2', 'Opción 3']
return <Menu options={menuOptions} />
}
}
class Menu extends React.Component {
constructor(props) {
super(props)
}
render() {
let options = this.props.options
return (
<ul>
{options.map(option => <li>{option}</li>)}
</ul>
)
}
}
ReactDOM.render(<App />, document.getElementById('app')
```
####*Estado*
Además de las props, los componentes en React pueden tener estado. Lo característico del estado es que si éste cambia, el componente se renderiza automáticamente. Veamos un ejemplo de esto.
Si tomamos el código anterior y en el componente <App />guardamos en su estado las opciones de menu, el código de App sería así:
```javascript
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
menuOptions: ['Opción 1', 'Opción 2', 'Opción 3']
}
}
render() {
return <Menu options={this.state.menuOptions} />
}
}
```
De ésta manera, las "opciones" pertenecen al estado de la aplicación (App) y se pueden pasar a componentes hijos (Menu) a través de las props.-
Ahora, si queremos cambiar el estado, añadiendo una nueva opción al menú tenemos a nuestra disposición la función setState, que nos permite modificarlo.
Aprovechando esto, vamos a modificar el estado a través de un evento disparado desde el componente hijo hacia el padre
####*Eventos*
Si las propiedades pasan de padres a hijos, es decir hacia abajo, los eventos se disparan hacia arriba, es decir de hijos a padres. Un evento que dispare un componente, puede ser recogido por el padre.
Veámoslo con un ejemplo. El componente ***`<Menu />`*** va a tener una nueva propiedad llamada onAddOption:
```javascript
render() {
return (
<Menu
options={this.state.menuOptions}
onAddOption={this.handleAddOption.bind(this)}
/>
)
}
```
Esta propiedad va a llamar a la función handleAddOption en <App /> para poder modificar el estado:
```javascript
handleAddOption () {
this.setState({
menuOptions: this.state.menuOptions.concat(['Nueva Opción'])
})
}
```
Cada vez que se llame a la función, añadirá al estado el item Nueva Opción. Cómo dijimos al inicio, cada vez que se modifique el estado, se "re-renderizará" el componente y veremos en el navegador la nueva opción añadida.
Para poder llamar a esa función, necesitamos disparar un evento desde el hijo. Voy a añadir un elemento <button> y utilizar el evento onClick de JSX, que simula al listener de click del ratón y ahi llamaré a la función "propiedad" onAddOption del padre.
El código de completo es:
```javascript
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
menuOptions: ['Opción 1', 'Opción 2', 'Opción 3']
}
}
render() {
return (
<Menu
options={this.state.menuOptions}
onAddOption={this.handleAddOption.bind(this)}
/>
)
}
handleAddOption () {
this.setState({
menuOptions: this.state.menuOptions.concat(['Nueva Opción'])
})
}
}
class Menu extends React.Component {
constructor(props) {
super(props)
}
render() {
let options = this.props.options
return (
<div>
<ul>
{options.map(option => <li>{option}</li>)}
</ul>
<button onClick={this.props.onAddOption}>Nueva Opción</button>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('app'))
```
Cada vez que hagamos click en el botón, llamará a la función que le llega por props. Ésta función, llama en el componente padre (App) a la función handleAddOption y la bindeamos con this, para que pueda llamar a this.setState dentro de la función. Éste setState modifica el estado y llama internamente a la función render lo que provoca que se vuelva a "pintar" todo de nuevo.
Y así es como funciona básicamente un componente de React. Más adelante veremos cuales son lo métodos de ciclo de vida y cómo utilizarlos.
####*PropTypes*
Para especificar propTypes, hacemos lo mismo que al crear componentes con clases: primero definimos el componente y después los propTypes.
```javascript
const Saludo = ({ name }) =>
<h1> Hola, {name}! </h1>
;
Saludo.propTypes = { name: PropTypes.string };
Saludo.defaultProps = { name: 'amigo' };
```
####*Contexto*
Los componentes también reciben un segundo parámetro que representa el contexto. Para requerirlo, utilizamos el mismo método que al definir props pero con contextTypes.
```javascript
const Saludo = ({ name }, context) =>
<h1 style={context}> Hola, {name}!</h1>;
;
...
Saludo.contextTypes = {
fontFamily: React.PropTypes.string
};
```
####*Ventajas*
Ahora que sabemos como utilizar estos componentes, podemos revisar que ventajas nos ofrecen en comparación con usar clases o React.createClass.
React de la manera correcta. El mismo equipo detrás de React ha declarado que este tipo de componentes es la manera apropiada de crear componentes sin estado y que en un futuro se le dará mayor atención y mejoras a los mismos.
Mas componentes, menos código. Al tener que usar tan poco código, este método promueve el uso de micro-componentes sin tener que aumentar la base de código considerablemente.
Mayor legibilidad. Usando componentes funcionales podemos simplificar partes de la aplicación y reducir el código. Además, quitamos un poco de la "magia" que agrega el usar clases.
Mejor testeabilidad. Al no tener estado garantizamos que el componente es una función pura que siempre nos regresara lo mismo dados los mismos props, por lo que nuestras pruebas unitarias son más sencillas y seguras.
Código agnóstico a React. Digamos que en un futuro queremos remplazar React por otra librería que nos ofrece mejor rendimiento. Si usamos React.Component y métodos como render(), tenemos que modificar todo el componente para acomodarse a cualquier otro nombre de método que utilice esa librería. En cambio, con componentes funcionales podemos utilizar cualquier librería que emplee JSX sin tener que reescribir por completo nuestro componente.
####*Desventajas.*
Aunque los componentes funcionales son geniales, tienen algunas desventajas que puede que sean relevantes para algunos (aunque la mayoría se planean resolver en un futuro).
No hay métodos de ciclo de vida. Este es un arma de doble filo. Si bien en la mayoría de los componentes es mejor que no tengamos estado, hay algunos en los que ocupamos si o si tener estado o realizar ciertas acciones al montar un componente (por ejemplo, en los componentes de orden superior). Para estos casos actualmente tenemos que regresar a usar clases, aunque en un futuro se planea permitir estado en estos tipos de componentes.
Difícil de optimizar. Debido a que no tenemos métodos del ciclo de vida del componente, no podemos utilizar shouldComponentUpdate para optimizar el diff en la aplicación. Probablemente en un futuro tengamos algo para compensarlo pero por ahora no hay manera de hacerlo.
No son compatibles con Hot-Reload. Probablemente la mayor de las razones por las que personalmente no he adoptado por completo los componentes funcionales es que actualmente ni react-hot-loader ni react-transform-hmr permiten usar hot-reload con componentes funcionales (debido a que no son tan fácil de identificar en comparación a los componentes propiamente instanciados). Por el lado positivo, se está trabajando continuamente en ello.
####*¿Cómo funciona React.js?*
React es una biblioteca escrita en JavaScript, desarrollada en Facebook para facilitar la creación de componentes interactivos, reutilizables, para interfaces de usuario. Se utiliza en Facebook para la producción de componentes, e Instagram está escrito enteramente en React. Uno de sus puntos más destacados, es que no sólo se utiliza en el lado del cliente, sino que también se puede representar en el servidor, y trabajar juntos.
####*¿Cómo funciona React?*
React.js está construido en torno a hacer funciones, que toman las actualizaciones de estado de la página y que se traduzcan en una representación virtual de la página resultante. Siempre que React es informado de un cambio de estado, vuelve a ejecutar esas funciones para determinar una nueva representación virtual de la página, a continuación, se traduce automáticamente ese resultado en los cambios del DOM necesarios para reflejar la nueva presentación de la página.
A primera vista, esto suena como que fuera más lento que el enfoque JavaScript habitual de actualización de cada elemento, según sea necesario. Detrás de escena, sin embargo, React.js hace justamente eso: tiene un algoritmo muy eficiente para determinar las diferencias entre la representación virtual de la página actual y la nueva. A partir de esas diferencias, hace el conjunto mínimo de cambios necesarios en el DOM.
Pues utiliza un concepto llamado el DOM virtual que hace selectivamente sub-árboles de los nodos sobre la base de cambios de estado, desarrollando esto, con la menor cantidad de manipulación DOM posible, con el fin de mantener los componentes actualizados, estructurando sus datos.
####*¿Cómo funciona el DOM virtual?*
Imagina que tienes un objeto que es un modeló en torno a una persona. Tienes todas las propiedades relevantes de una persona que podría tener, y refleja el estado actual de la persona. Esto es básicamente lo que React hace con el DOM.
Ahora piensa, si tomamos ese objeto y le hacemos algunos cambios. Se ha añadido un bigote, unos bíceps y otros cambios. En React, cuando aplicamos estos cambios, dos cosas ocurren:
- En primer lugar, React ejecuta un algoritmo de "diffing", que identifica lo que ha cambiado.
- El segundo paso es la reconciliación, donde se actualiza el DOM con los resultados de diff.
La que hace React, ante estos cambios, en lugar de tomar a la persona real y reconstruirla desde cero, sólo cambiaría la cara y los brazos. Esto significa que si usted tenía el texto en una entrada y un actualización se llevó a cabo, siempre y cuando nodo padre de la entrada no estaba programado para la actualización, el texto se quedaría sin ser cambiado.
Es así como React, está tomando un gran auge, llegando a ser más usado.
React: validación de propiedades con propTypes
Jul 26, 2016 | Front End, react | 0 comentarios
Los componentes en React están diseñados para poder agruparlos en componentes más grandes y ser reutilizados, ya sea en el mismo proyecto, en otros proyecto o por otros desarrolladores. Por lo tanto es una buena práctica definir explícitamente las propiedades que acepta un componentes, cuáles son requeridas y los tipos de dato de cada una.
Este es el propósito propTypes de un componente, y entre otras cosas nos ayudará a:
– Revisar rápidamente cuáles son las propiedades que debemos pasar a un componente
– Cuándo hay un error, React mostrará un mensaje en la consola indicando qué propiedades faltan y qué método generó el problema.
El objeto propTypes se define como una propiedad en el constructor de la clase, en el siguiente ejemplo tenemos un componente Titulo que recibe una propiedad nombre que se muestra dentro de un encabezado.
Para especificar que esa propiedad debe ser cadena indicamos el tipo PropTypes.string.isRequired, la última parte isRequired es opcional y con ella especificamos si es una propiedad obligatoria.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment