Aprende Javascript con MentoringJS - Step 10

En este artículo voy a mostrar todos los ejercicios del tutorial de react.express y voy a analizar todos los ejemplos explicando qué significa cada parte de código.

Para realizar este artículo he utilizado varios tutoriales y fuentes con los que empezar a conocer y familiarizarme con React.


Para empezar, es necesario realizar la instalación (o setup) de todas las herramientas necesarias para llevar a cabo los ejercicios en tu propio ordenador. Es cierto que actualmente hay muchas opciones de programar, inclusor React, a través de webs específicas sin necesidad de instalaciones previas. Bajo mi punto de vista, para aprender y sentirse cómodo con las tecnologías utilizadas es mucho mejor realizarlo en local.

En primer lugar, hay que instalar nodejs. Como dicen en su web, node.js es:

Un entorno de ejecución para JavaScript construido con el motor de JavaScript V8 de Chrome.

Con el entorno node.js instalado se podrá utilizar el sistema de paquetería específico npm para instalar los paquetes necesarios para poder desarrollar en React.

En el tutorial de react.express nos dan dos opciones.

  1. La más sencilla es utilizar npm para instalar el paquete específico create-react-app. Con esta instalación es muy sencillo establecer el entorno de desarrollo necesario para poder pasar a programar rápidamente.

    Para instalar create-react-app con npm se tendría que realizar los siguientes comandos:

    npm install -g create-react-app
    

    Posteriormente, para crear e inicializar una app React y poder empezar a programar se tendría que escribir:

    create-react-app my-app
    cd my-app/
    npm start
    

    Con la última orden se abrirá un navegador mostrando el código por defecto del archivo src/App.js.

  2. La segunda opción es instalar manualmente webpack, babel y React.

    Webpack

    npm install --save-dev webpack webpack-dev-server
    

    Babel

    npm install --save-dev babel-loader babel-core babel-preset-react babel-preset-env babel-preset-stage-1 babel-plugin-transform-runtime
    npm install --save babel-runtime
    

    React

    npm install --save react react-dom
    

    En los tres pasos hay que hacer cambios en ciertos archivos para que la configuración sea correcta y funcione todo bien.

Nota: como todos los ejemplos están adaptados a esta segunda opción de instalación he decidido seguir también esta vía. Los ejemplos se podrían haber adaptado a la primera configuración, más sencilla y habitual, pero he querido ser fiel al tutorial.

Para seguir el tutorial hay que hacer todo lo que indica en el setup e instalar todas las herramientas ya que sino pueden aparecer errores al intentar ejecutar el index.js de React.


Índice de ejercicios

  1. ReactDOM
  2. DOM Components
  3. Custom Components
  4. Component API
  5. Inline Styles
  6. CSS-in-JS


1. ReactDOM

import React from 'react'
import { render } from 'react-dom'

const node = document.querySelector('#app')
const element = <div>Hello World!</div>

render(element, node)

Lo primero que aparece es las dos primeras líneas son imports. Esto se hace para importar las dos librerías básicas que nos servirán para trabajar con React:

import React from 'react'

Este import se realiza para importar la librería necesaria para crear componentes.

import { render } from 'react-dom'

Este import se realiza para importar la librería necesaria para renderizar o representar el contenido en el DOM.

Después se declaran dos variables con const (en ES6). La primera, node se hace para seleccionar un nodo del DOM en nuestra app para renderizar el contenido. Esto se hace seleccionando el atributo app que está añadido en el index.html

La segunda variable, element, se añade contenido en formato JSX.

JSX es un tipo de expresión de Javascript, basada en tags como XML. La lógica interna que ha llevado a utilizar este tipo de expresión en React es debido a que no se quiere separar los diferentes tipos de expresión que se pueden generar en la UI (Interficies de usuario) ya que React separa problemas y no tecnologías. JSX es un atajo para usar la API de React.createElement() y la que se encarga de transformar o compilar las expresiones JSX en Javascript estándar es Babel.

La última línea sirve para renderizar la variable element en el nodo DOM.

render(element, node)

Volver al Índice


2. DOM Components

import React from 'react'
import { render } from 'react-dom'

const node = document.querySelector('#app')
const element = (
	<div>
		<input type={'text'} defaultValue={'Type here!'} />
		<select>
			<option>A</option>
			<option>B</option>
		</select>
		<img src={'https://images.unsplash.com/photo-1539980307411-6820f89db71b?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=a613de46106ddfc2cddbd4aaf6e4b437&auto=format&fit=crop&w=987&q=80'}

	</div>
)

render(element, node)

Este ejemplo solo cambia del anterior en el contenido de la variable element. En el div se añaden diversas etiquetas HTML como input, select o img para añadir contenido, bien sea para añadir texto, seleccionar varias opciones o añadir una imagen.


3. Custom Components

import React, { Component } from 'react'
import { render } from 'react-dom'

class Card extends Component {
  render() {
    const style = {
      margin: 20,
      padding: 20,
      color: 'white',
      backgroundColor: this.props.color,
    }

    return (
      <div style={style}>
        {this.props.children}
      </div>
    )
  }
}

const node = document.querySelector('#app')
const element = (
  <div>
    <Card color={'skyblue'}>Card 1</Card>
    <Card color={'steelblue'}>Card 2</Card>
  </div>
)

render(element, node)

En este ejemplo hay varios cambios con el ejemplo anterior.

El primero es en el primer import. Ahí se ve que se ha añadido {component} a la hora de importar. Esto quiere decir que se va a importar un Componente de la librería React.

Acto seguido se añade el Componente en forma de clase (class).

Según la documentación de React, los componentes te permiten:

Dividir la Interficie de Usuario en piezas independientes y reutilizables y pensar en cada pieza por ella misma. Los componentes conceptualmente son como funciones de Javascript. Aceptan que se le pasen parámetros (que se llaman props) y devuelven elementos React describiendo lo que debería aparecer en pantalla.

Hay dos maneras de expresar un Componente, mediante una función y mediante una clase. En el ejemplo de arriba se utiliza una clase. Estas clases utilizan sintaxis ES6.

Respecto al ejercicio, decir que el componente se crea con una clase llamada Card.

class Card extends Component {}

Esta sintaxis quiere decir que la clase creada se extiende a React.Component.

Después se añade un método llamado render() donde va todo el contenido del componente. Ahí se añaden estilos CSS y también se declara el color de fondo como receptor de una props que le vendrá de fuera y que añadirá dicho color.

Hay que puntualizar que, en las clases con los valores que se reciben de fuera no se utiliza la sintaxis de props sino this.props.

La clase devuelve los estilos y también el color de fondo que deberán recibir como this.props.

El valor que recibirá el color de fondo de la clase se le pasa en la variable element. Ahí, se llama a la clase Card dos veces, cada una con un color de fondo diferente. Y esto es lo que se renderiza al final.

Volver al Índice


4. Component API

import React, { Component } from 'react'
import { render } from 'react-dom'

class Counter extends Component {

  state = {count: 0}

  componentDidMount() {
    setInterval(() => {
      this.setState({count: this.state.count + 1})
    }, 1000)
  }

  render() {
    const {count} = this.state
    const {color, size} = this.props

    return (
      <div style=>
        {count}
      </div>
    )
  }
}

class App extends Component {
  render() {
    const style = {
      flex: 1,
      justifyContent: 'center',
      alignItems: 'center',
    }

    return (
      <div style={style}>
        <Counter color={'lightblue'} size={16} />
        <Counter color={'skyblue'} size={32} />
        <Counter color={'steelblue'} size={80} />
        <Counter color={'darkblue'} size={140} />
      </div>
    )
  }
}

render(<App />, document.querySelector('#app'))

En este ejemplo se incluye un componente Contador (Counter) que mantiene el tiempo transcurrido internamente como state.count. El componente App renderiza el componente Contador con dos props: el tamaño y el color.

Este ejercicio añade varios puntos que son importantes a la hora de entender React, como por ejemplo el estado (state). En los componentes se les puede pasar state y props. Los segundos serían como los argumentos de las funciones de javascript, mientras que los primeros serían como el estado interno del componente que, eventualmente, puede cambiar.

Lo primero que hace el componente Counter es añadir el método state con una propiedad, en este caso count. Esta propiedad count se inicializa con un valor de 0.

El state lo define el usuario y debe ser un objeto Javascript.

state = {count: 0}

Posteriormente, se añade el método componentDidMount().

componentDidMount() {
	setInterval(() => {
		this.setState({count: this.state.count + 1})
	}, 1000)
}

Los componentes tienen un ciclo de vida y en cada momento se puede y se debe utilizar un método diferente.

A componentDidMount() se le llama cuando una instancia de un componente está siendo creado e insertado en el DOM. La inicialización que requiera nodos de DOM debe ir en este método, por lo que es el sitio idóneo para poner que se actualice el contador cada vez.

Respecto a la función setInterval, se establece para actualizar el valor del contador (count) cada segundo. Esta función se establece en formato arrow functions.

Las arrow functions se usan para declarar funciones anónimas y tienen dos importantes características: el uso de this es diferente del de las funciones tradicionales y no tienen argumentos.

Para actualizar el contador se pasa un objeto al método this.setState. Este método es la manera que tienen los componentes de actualizar su estado. El objeto pasado es el contador count actualizado con un valor de +1. Esto se hace con this.state que es la manera de acceder al estado de un componente.

render() {
	const {count} = this.state
	const {color, size} = this.props

	return (
		<div style=>
			{count}
		</div>
	)
}

Después se añade un método llamado render() donde va el contenido del componente. Ahí se declaran tres variables, count y color y size. La primera se iguala a this.state para poder utilizarla directamente como {count} sin necesidad de escribir todas las veces this.state.count. Las segundas se iguala a this.props ya que recibirá dos parámetros de fuera del Componente con ciertos valores que se devolverán en el apartado return.

class App extends Component {
  render() {
    const style = {
      flex: 1,
      justifyContent: 'center',
      alignItems: 'center',
    }

    return (
      <div style={style}>
        <Counter color={'lightblue'} size={16} />
        <Counter color={'skyblue'} size={32} />
        <Counter color={'steelblue'} size={80} />
        <Counter color={'darkblue'} size={140} />
      </div>
    )
  }
}

En el componente App se añaden ciertos estilos en render con el método styel y después se devuelve un div este método y llamando al contador del componente Counter con dos argumentos, el color y el tamaño.

Al final se renderiza este componente App.

render(<App />, document.querySelector('#app'))

Volver al Índice


5. Inline Styles

import React, { Component } from 'react'
import { render } from 'react-dom'

const randomColor = () => '#' + Math.random().toString(16).substr(-6)

class Card extends Component {
  render() {
    const style = {
      padding: 20,
      textAlign: 'center',
      color: 'white',
      backgroundColor: this.props.color,
    }

    return (
      <div style={style}>
        {this.props.children}
      </div>
    )
  }
}

class App extends Component {

  state = {
    color: 'skyblue'
  }

  randomizeColor = () => this.setState({color: randomColor()})

  render() {
    const {color} = this.state

    const style = {
      padding: 20,
    }

    return (
      <div style={style}>
        <Card color={color}>
          <input
            type={'button'}
            value={'Randomize Color'}
            onClick={this.randomizeColor}
          />
        </Card>
      </div>
    )
  }
}

render(<App />, document.querySelector('#app'))

En este ejemplo se construye un botón en el que, al pinchar en él, cambia de color de fondo de manera aleatoria. Esto se hace pasando estilos CSS a un DOM component.

Yendo al código, lo primero y más significativo es la variable randomColor, que almacena una función dónde, utilizando la función Math.random, se genera un número aleatorio entre 0 y 1 con decimales. Después, la función toString la convierte a Hexadecimal y, por último, la función substr devuelve 6 caracterés de ese string. Con eso y el # inicial se consigue un color en Hexadecimal.

const randomColor = () => '#' + Math.random().toString(16).substr(-6)
class Card extends Component {
  render() {
    const style = {
      padding: 20,
      textAlign: 'center',
      color: 'white',
      backgroundColor: this.props.color,
    }

    return (
      <div style={style}>
        {this.props.children}
      </div>
    )
  }
}

El componente Card en el método render añade los estilos CSS con el método style y también acepta un argumento del color de fondo como una propiedad de dicho método. En la parte del return retorna el método style con todas las propiedad CSS antes definido y también el argumento recibido. Esto lo hace con this.props.children que es un props especial, típicamente definido por las tags hijas en una expresión JSX y que hace referencia al this.props.color del método style.

state = {
	color: 'skyblue'
}

randomizeColor = () => this.setState({color: randomColor()})

render() {
	const {color} = this.state

El componente App establece el color de fondo inicial, inicializándolo con el método state. Después se añade una función randomizeColor donde se cambia el color con this.setState y aplicando a la variable color la función randomColor para que se cambie aleatoriamente el color de fondo.

En la parte de render se iguala la variable color a this.state para poder utilizarla directamente como {color} sin necesidad de escribir todas las veces this.state.color y también se añade un método style con una propiedad CSS.

Posteriormente, en return es dónde se renderiza todo.

return (
	<div style={style}>
		<Card color={color}>
			<input
				type={'button'}
				value={'Randomize Color'}
				onClick={this.randomizeColor}
			/>
		</Card>
	</div>

Aquí se puede ver que se establece el estilo inicial del componente App. Después se llama al componente Card con la variable color como prop. Después se añade un input con un botón y un texto y un evento onClick llamando a la función randomizeColor para cambiar el color cada vez que se pinche sobre el botón.

Al final se renderiza este componente App.

Volver al Índice


6. CSS-in-JS

import React, { Component } from 'react'
import { render } from 'react-dom'
import styled from 'styled-components'

const randomColor = () => '#' + Math.random().toString(16).substr(-6)

const Card = styled.div`
  padding: 20px;
  text-align: center;
  color: white;
  background-color: ${props => props.color};
`

const Container = styled.div`
  padding: 20px;
`

class App extends Component {

  state = {
    color: 'skyblue'
  }

  randomizeColor = () => this.setState({color: randomColor()})

  render() {
    const {color} = this.state
    return (
      <Container>
        <Card color={color}>
          <input
            type={'button'}
            value={'Randomize Color'}
            onClick={this.randomizeColor}
          />
        </Card>
      </Container>
    )
  }
}

render(<App />, document.querySelector('#app'))

Este ejemplo tiene casi el mismo código que el anterior, exceptuando lo que hace referencia a los estilos que lo hace con una sintaxis diferente.

const Card = styled.div`
  padding: 20px;
  text-align: center;
  color: white;
  background-color: ${props => props.color};
`

Esta sintaxis se llama styled components y es casi igual al CSS estándar. Para utilizarla en React se debe importar la libreía con:

import styled from 'styled-components'

El resto de código es igual que el ejemplo anterior. Como significativo hay que comentar que el componente Card sigue existiendo pero con la sintaxis específica de styled components y también la manera en la que recibe el argumento con props.


En breve estará disponible la segunda parte de este repaso del tutorial de react.express.

To be continued …