React

⚛️

Historia

2010

Un día cualquiera en las oficinas de Facebook


XHP

if ($_POST['name']) {
?>
  Hello, <?=$_POST['name']?>.
} else {
?>
  <form method="post">
    What is your name?
    <input type="text">
    <input type="submit">
  </form>
}
if ($_POST['name']) {
 echo Hello, {$_POST['name']};
} else {
  echo 
  <form method="post">
    What is your name?
    <input type="text" />
    <input type="submit" />
  </form>;
}

2011

Primeros prototipos de React

Jordan Walke

Primeros prototipos de React

2012


Jordan Walke

Pete Hunt

2013

"Big Launch"

Jordan Walke introduce React

Los asistentes pensaron que era una vuelta atrás 😱

React Tour! 🎪

"Big Launch"

2 junio React en JSFiddle

30 julio React en Ruby on Rails

19 agosto React en Python

2014

React Developer Tools

Reactivex.io

React Hot Loader

2015

React canvas

Netflix likes React

Airbnb uses React

React Native

Redux

2016

Mobx

Draft.js

React Storybook

Error Code System

2017

Relicensing

React fiber

2018

Sneak Peek Beyond React 16 🎬


Sophie Alpert
@sophiebits


Andrew Clark
@acdlite


Dan Abramov
@dan_abramov

Octubre 2018

React today and tomorrow

React hooks

Concurrent Rendering in React

Conf 2018

Conf 2018

Conf 2018

Conf 2018

Conf 2018

Conf 2018

¿Quiénes lo usan?

🤔🤔

Websites built with React

Programación declarativa

✍️📝

Programación imperativa 👉❗

Cuando pulso en botón A
Vete al componente con id="texto"
Accede a su campo HTML
Añade un <div>
Y le pones el texto "HOLA"

Programación declarativa ✍️📝

Cuando pulso el botón A
El texto = "Hola"

¿Qué no es React?

✋⛔

No es un framework MVC

No es un sistema de plantillas

¿Qué es React?

✅ ⚛️

Es una librería JS para construir interfaces de usuario

Cambio de chip

🐿️♻️

DOM (ojos HTML y CSS)


<html>
<head>
  <meta/>
  <title>Página sencilla</title>
</head>
<body>
<p>Esta página es <strong>muy sencilla</strong></p>
</body>
</html>

DOM (ojos JS)

DOM (ojos React)

DOM (ojos React)

Virtual DOM

🔮📏

Apagar vela (modo JS)

const tarta = document.getElementById('tarta');
const vela = tarta.getChildren()[0];
const fuego = vela.getChildren()[0];
fuego.parentNode.removeChild();

Apagar vela (modo React)

tarta.apagarVela();

¿Por qué es tan rápido?

🎯🎨

React Fiber

React Fiber

React Fiber

React Fiber

React Fiber

JSX

👩‍💻🎨👨‍💻

Es una extensión de JS inspirada en XML

Añadir una fila a una tabla (modo JS)

function addRow(tableID) {
  const table = document.getElementById(tableID);
  const rowCount = table.rows.length;
  const row = table.insertRow(rowCount);
  const cell = row.insertCell(0);
  cell.innerHTML += " <input type=\"text\" size=\"20\" name=\"values[]\"/>" +
    "<INPUT type=\"button\" class=\"btn_medium\" value=\"Remove\" " +
    "onclick=\"this.parentNode.removeChild(this.parentNode);\" />" +
    "<br>" +
    "<small><font color=\"gray\">Enter Title</font></small>";
}

Añadir una fila a una tabla (modo React)

const render = () => {
  <input type="text" size="20" name="values[]"/>
  <input type="button" className="btn_medium" value="Remove" onclick={removeMe()}/>
  <br>
    <small><font color="gray">Enter Title</font></small>
    };

¿Se puede usar React sin JSX?

Componente sin JSX

const HelloWorld = () =>
  React.createElement('div', {className: 'hello'}, 'Hello World!');

Componente con JSX

const HelloWorld = () =>
  <div className="hello">Hello World!</div>;

Comparativa

const HelloWorld = () =>
  React.createElement('div', {className: 'hello'}, 'Hello World!');

const HelloWorld = () =>
  <div className="hello">Hello World!</div>;

Props vs State

✳️ 🥊🥊

<CounterButton text="Clicks: "/>

Propiedades

No se modifican NUNCA dentro del componente

Estados

Se modifican DENTRO del componente usando hooks

Hooks

🔗 🥊

https://github.com/reactjs/rfcs/pull/68

Pero antes...

Class components

React Stateless Functional Components

Class Component

export class Hello extends React.Component {
  render() {
    return <h1>Hello {this.props.name}</h1>
  }
}

React Stateless Functional Component

export function Hello(props) {
  return <h1>Hello {props.name}</h1>
}

Simplificando

export const Hello = ({name}) =>
  <h1>Hello {name}</h1>;

Comparativa

export class Hello extends React.Component {
  render() {
    return <h1>Hello {this.props.name}</h1>
  }
}
export const Hello = ({name}) =>
  <h1>Hello {name}</h1>;

Pero...

React Stateless Functional Component


Hooks al rescate!

David Haye vs Tony Bellew

Class Component con estado

export class Hello extends React.Component {
  render() {
    return <button onClick={this.increment}>${this.state.count}</button>
  }
}

FC con estado (usando hooks)

import {useState} from 'react';

export const Hello = () => {
  const [count, setCount] = useState(0);

  const increment = () => setCount(count + 1);

  return <button onClick={increment}>${count}</button>
}

Reglas de los hooks

Un hook es una función JS

toplevel un hook solo puede ser llamada al inicio

Hook solo en componentes funcionales

Nombres de los hooks empiezan por use

Ejemplos de hooks

🔗 🥊

useState

export const Hello = () => {
  const [count, setCount] = useState(0);

  const increment = () => setCount(count + 1);

  return <button onClick={increment}>{count}</button>
}

useEffect

export const Hello = () => {
  const [width, setWidth] = useState(window.innerWidth);

  const onResize = () => setWidth(window.innerWidth);

  useEffect(() => {
    window.addEventListener('resize', onResize);
    return () => {
      window.removeEventListener('resize', onResize);
    }
  }, []);

  return <h1>Width: {width}</h1>
}

useEffect (dependencias)

useEffect(() => {

}, []);

Sin dependencias

useEffect (dependencias)

useEffect(() => {

});

En cada render

useEffect (dependencias)

useEffect(() => {

}, [name, age]);

Cada vez que se modifiquen name y/o age

Más hooks

usehooks.com

Collection of React Hooks

¿Cómo se distribuye React?

📦 ↗️

react

react-dom

react-dom-server

react-native

Y... ¿Puedo usar react con...?











Crear un proyecto de React + TS (usando CRA)

Crear un componente con un botón que al pulsarlo lance un dado de 6 caras e imprima el resultado

Componentes

🧩

Atomic Web design

🧩

Átomos

input

button

ul

img

Moléculas

Search

label

input

button

Organismos

Header

Navigation

Search

Plantillas

Login

List

Charts

Páginas

Index

MyProfile

About

Checklist

Un componente 👉 encapsula su lógica de dominio

Un componente 👉 única responsabilidad

Piensa en tests

Reutiliza código (hooks)

NumberPicker

Crear un nuevo componente NumberPicker

Mínimo y máximo

Pensando en Atomic Web Design diseñar los mockups necesarios para crear el front sacando nombre de los componentes

Styles

🎨💄

NumberPicker

className

NumberPicker.tsx

export const NumberPicker: FC = () => {
  const [count, setCount] = useState<number>(0);

  const increase = () => setCount(count => count + 1);
  const decrease = () => setCount(count => count - 1);

  return <div className="number-picker">
    <button class="number-picker-buttons" onClick={decrease}>-</button>
    <p className="number-picker-label">{count}</p>
    <button class="number-picker-buttons" onClick={increase}>+</button>
  </div>
}

index.tsx

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';  // 👈👈
import App from './App';
import reportWebVitals from './reportWebVitals';

index.css

.number-picker {
  display: flex;
  align-content: center;
  align-items: center;
  gap: 20px;
  margin: 20px;
}
.number-picker-label {
}

.number-picker-buttons {
}

style

The React way

NumberPicker.tsx

const numberPickerStyle: CSSProperties = {
  display: 'flex',
  alignContent: 'center',
  alignItems: 'center',
  gap: '20px',
  margin: '20px'
};

NumberPicker.tsx

export const NumberPicker: FC = () => {
  return <div style={numberPickerStyle}>
    <button style={numberPickerButtonStyle} onClick={decrease}>-</button>
    <p style={numberPickerLabelStyle}>{count}</p>
    <button style={numberPickerButtons} onClick={increase}>+</button>
  </div>
}

index.css ?? 🤔

.number-picker {
  display: flex;
  align-content: center;
  align-items: center;
  gap: 20px;
  margin: 20px;
}
.number-picker-label {
}

.number-picker-buttons {
}

CSS Modules

NumberPicker.tsx

import styles from './NumberPicker.modules.css';

export const NumberPicker: FC = () => {
  return <div className={styles.container}>
    <button style={styles.buttons} onClick={decrease}>-</button>
    <p style={styles.label}>{count}</p>
    <button style={styles.buttons} onClick={increase}>+</button>
  </div>
}

Resultados

ClassName

style

CSS Modules

¿Cuál usamos?

https://github.com/MicheleBertoli/css-in-js

Formularios

⌨️🔠

Controlled Components

Uncontrolled Components

El problema

Los componentes <input> <textarea> <select> en el DOM tienen su propio estado

Controlled components ▶️

const LoginForm = () => {
  const [email, setEmail] = useState<string>('');

  const doLogin = () => console.log('Email', email);
  const onChangeEmail = (event) => setEmail(event.target.value);

  return <form onSubmit={doLogin}>
    <input type="email" value={email} onChange={onChangeEmail}/>
  </form>
}

Uncontrolled components ▶️

const LoginForm = () => {
  const doLogin = (event: FormEvent<HTMLFormElement>) => {
    const formJSON = formToJSON(event.currentTarget);
    console.log(formJSON);
  }

  return <form onSubmit={doLogin}>
    <input type="email"/>
  </form>
}

Uncontrolled components (hooks) ▶️

import {FormEvent, useRef} from "react";

const LoginForm = () => {
  const emailRef = useRef<HTMLInputElement>(null);

  const doLogin = (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    console.log(emailRef.current?.value);
  }

  return <form onSubmit={doLogin}>
    <input ref={emailRef} type="email"/>
  </form>
}

Otras posibilidades

React Hook Form

React Final Form

Formik

Router

🚋🚦🛣️

¿Qué es un router?

Pero...

Pero...

react === UI/UX

React Router

Declarative routing for React

Instalación

npm i react-router-dom

App.tsx

return App = () => <div>
  <Header/>
  <Routes>
    <Route path="/" element={<Home/>}/>
    <Route path="about" element={<About/>}/>
    <Route path="*" element={<Page404/>}/>
  </Routes>
  <Footer/>
</div>;

Ejemplo

React Router Examples

Global State

⚛️🌎

React

Flux & Redux

2014

Rethinking Web App Development 🎬


Tom Occhino


Jing Chen


Pete Hunt

¿Es posible?

MVC

Video ▶️

¿Por qué no es escalable?

Previsibilidad

Previsibilidad

Que puede ser previsto o está en las previsiones normales


Andrew Clark
@acdlite


Dan Abramov
@dan_abramov

mobx

¿Qué es un mobx?

Simple, scalable state management

No fliparse!

React & Backend

🔌💿

React go wall

Get movies

const MoviesPage = () => {
  const {movies, isLoading, error} = useGetMovies();

  if (isLoading) {
    return <div>Loading movies...</div>;
  }

  if (error) {
    return <div>Ups!</div>;
  }

  if (!movies) {
    return <div>Ups! no movies</div>;
  }

  return <ul>
    {movies.map(movie => <Movie key={movie.id} movie={movie}/>)}
  </ul>;
}

Movie component

export const Movie: FC<any> = ({movie}) => {
  return <li>{movie.name}</li>
};

Custom hook (useGetMovies)

export const useGetMovies = () => {
  const [movies, setMovies] = useState<any[]>();
  const [isLoading, setIsLoading] = useState<boolean>(true);
  const [error, setError] = useState<any>();

  useEffect(() => {
    loadMovies()
      .then(movies => setMovies(movies))
      .catch(err => setError(err))
      .finally(() => setIsLoading(false))
  }, []);

  return {
    movies,
    isLoading,
    error
  }
};

Query method

const loadMovies = (): Promise<any[]> => {
  return new Promise((resolve, reject) => {
    fetch('http://127.0.0.1:3000/movies')
      .then(response => response.json())
      .then(movies => resolve(movies))
      .catch(err => reject(err));
  });
}

Usando hooks externos

"React Query"

swr