Functional Reactive Programming (FRP)
1. Functions at the heart of code
2. Data mutation is Bad (should be avoided)
1. Composability → The system is seen as a composition
of functions
2. Purity → functions which are free of side-effects and
don't mutate their own arguments
3. Higher Order functions → Have a function as an
argument and/or return another function
4. Immutability → functions always return a new object /
array or function derived from the arguments, but the
arguments remain the same
PREDICTABILITY
FRP - Examples
function sumArray(values) {
return values
.map(Number)
.reduce((total, value) => total + value);
}
sumArray([1, '2', '30']); // 33
function push(array, element) {
// Add new element to array
array.push(element);
return element;
}
function concat(array, elements) {
// Create new array with all values
return array.concat(elements);
}
let arr = [1, 2, 3];
let addMore = true;
// Adding elements:
arr.push(4, 5);
if (addMore) {
arr.push(6, 7);
}
// Or the functional way
arr = arr
.concat([4, 5])
.concat(addMore ? [6, 7] : []);
ReactJS and FRP
ReactJS fits the FRP Paradigm:
1. UI is predictable → ReactDOM.render();
2. UI is composable →
<ParentComonent><ChildComponent /></ParentComponent>
3. Higher-order components give us more code reusability and increase
composability.
a. A component taking a component as an argument and wrapping
aditional content around it to provide some context. This would be
the case of a modal component.
b. A component returning another component (i.e. a factory). This
would be the case if you want to reuse the functionality of a base
component into a new component.
And what about Purity and Immutability? … AMEN !
Reactivity: One Way Binding
<ComponentA /> {this.props}
<ComponentB /> {this.props}
<ComponentC /> {this.props}
Update in parent props →
updates children props
<ComponentA /> {this.state} <ComponentB /> {this.props}
Update in parent state → updates children props
THE PROBLEM:
When we re-render a component, it will always return a new instance of
a DOM element. The old element would then be removed from the tree
and the new one would be added. With no existing mechanisms for the
DOM to know if those two elements are related, we would have to re-
render it completely.
THE SOLUTION:
A component is a function creating virtual DOM elements instead of real
DOM elements. When a re-rendering occurs, the virtual DOM runs a diff
algorithm to create a set of changes to apply to the real DOM (a patch)
Virtual DOM
1. An application has a state
2. This state is rendered in a tree of
components, using a Virtual DOM.
Data is flowing down the tree.
3. The rendered UI will generate
events from user interactions
which will update the application
state.
4. Following the state update, the UI
will be updated
5. The application state can also
receive updates from the server
Application Flow: The Flux Pattern
Server Side Rendering
BackEnd Rest API
Façade -
Middleware Server
Routing: React-Router
HTTP 200: React.
renderToString
HTML with full react
components rendered
Client: React &
React-Router
9flats - Airbnb - Alipay - Atlassian - BBC - Box - Capital
One - Coursera -Dailymotion - Deezer - Docker -
Expedia - Facebook - Fotocasa - HappyFresh - IMDb -
Instacart - Instagram - Khan Academy - Klarna - Lyft -
NBC - Netflix - NFL - Paypal - Periscope - Ralph Lauren -
Reddit - Salesforce - Stack Overflow - Tesla - Tmall -
The New York Times - Twitter Fabric - Twitter Mobile -
Uber - WhatsApp - Wired - Yahoo - Zendesk
Who is using ReactJS?
JSX is a JavaScript syntax extension that looks similar to XML. You can
use a simple JSX syntactic transform with React.
JSX is optional, however it is recommended because it is a concise and
familiar syntax for defining tree structures with attributes.
JSX
<div> texto </div>
<div className=”rojo”> texto </div>
<Menu className=”navbar” />
<UsersTable>
<User name=”Tyrion” />
</UsersTable>
The react-dom is a package provides DOM-specific methods that can be used at
the top level of your app and as an escape hatch to get outside of the React
model if you need to.
Method render: Render a ReactElement into the DOM in the supplied container
and return a reference to the component.
React-DOM
import ReactDOM from 'react-dom';
ReactDOM.render(
<App families={[“Stark”, “Lannister”, “Targaryen”,
“Baratheon” ]} />,
document.querySelector('.container'),
() => { console.log("I'm a callback, you know nothing");
);
Props:
are a Component's configuration, its options.
They are received from above and immutable
as far as the Component receiving them is
concerned.
A Component cannot change its props, but it is
responsible for putting together the props of its
child Components.
Only Props ? functional components
Props vs State
State:
The state starts with a default value when a
Component mounts and then suffers from
mutations in time (mostly generated from user
events).
A Component manages its own state internally,
but—besides setting an initial state—has no
business fiddling with the state of its children.
You could say the state is private.
If you need to use state or function hooks,
you need class based component
Props:
are a Component's configuration, its options.
They are received from above and immutable
as far as the Component receiving them is
concerned.
A Component cannot change its props, but it is
responsible for putting together the props of its
child Components.
Only Props ? functional components
Props vs State
State:
The state starts with a default value when a
Component mounts and then suffers from
mutations in time (mostly generated from user
events).
A Component manages its own state internally,
but—besides setting an initial state—has no
business fiddling with the state of its children.
You could say the state is private.
If you need to use state or function hooks,
you need class based component
- props state
Can get initial value from parent
Component?
Yes Yes
Can be changed by parent Component? Yes No
Can set default values inside Component?* Yes Yes
Can change inside Component? No Yes
Can set initial value for child Components? Yes Yes
Can change in child Components? Yes No
Form components such as <input>, <textarea>, and <option> differ from other
native components because they can be mutated via user interactions.
A controlled <input> has a value prop. Rendering a controlled <input> will
reflect the value of the value prop.
A controlled <input> has a value
prop. Rendering a controlled
<input> will reflect the value of the
value prop.
User input will have no effect on
the rendered element because
React has declared the value to be
Fire and Blood.
To update the value in response to
user input, you could use the
onChange event
handleChange: function(event) {
this.setState({value: event.target.value});
},
render: function() {
return (
<input type="text" value={this.state.value}
onChange={this.handleChange}
defaultValue=”Fire and Blood”
/>
);
Controlled components
https://github.com/rdavisual/react-project-base/tree/reactjs-game-3x3 esta rama esta creada desde el
punto donde se dejo el workshop.
El componente simplebox recibirá un nueva propiedad que será available(boolen). Dependiendo de
este parámetro el componente simplebox llamará a la función que se le pasa (clickHandle).
En el componente table añadir un nuevo atributo al state que sea “available” : true, pasar este nuevo
atributo a las simplebox como propiedad (en el render).
En la función de click de table cambiar el atributo del state available a false y comprobar que no se
vuelve a llamar al clicar cualquier celda.
resultado: solo se puede hacer un click a la table.
Ejercicio 1
Ejercicio 2
En el componente table modificar el state, en la parte del constructor, crear un único atributo que se
llamara table. Este tendrá un array de objetos que contendrán las propiedades de las “celdas” de
nuestra tabla. Cada objeto tendrá la siguiente estructura y valores iniciales:
{ id:<identificador único> , classBox: "", available: true};
En el momento de crear cada simplebox (en la función render), recogeremos del state los tributos
de cada celda y se los pasaremos a la simplebox. “Una simplebox - un objeto celda”a
Modificar la función clickHandler del componente table para que cambie el atributo classBox de la
celda que se ha asignado a la simpleBox. Recordar que el state no se actualiza, sino que se tiene
que reescribir entero (setState).
resultado: se cambia el color de la celda clicada.
Ejercicio 3
Creación de un nuevo componente: game
Este componente tendrá en el state 2 objetos de tipo jugador y un turn(turno del jugador) de tipo
string. El objeto jugador tendrá la siguiente estructura:
{ id:<identificador único> , nombre: "nombre jugador", classPlayer: “black”};
la classPlayer debe ser la clase que cambia de color la box ( black, red o alguna propia creada )
Este componente será el que renderice el componente de table.
resultado: enseña la misma tabla
Ejercicio 4
El componente table recibirá 2 nuevas propiedades: una función y la clase del color que se
querrá pintar. La clase dependerá del turno del jugador.
La función cambiará el turno del jugador.
En el componente table, en la función clickHandle se cambiará al color que se le haya pasado
por propiedades y al final de esta función se llamará a la función también pasada por
propiedades.
Finalmente en el render del componente game, aparte de mostrar la table mostrará el nombre
del jugador al que “le toca”.
resultado: clicks de diferentes colores
Ejercicio 5
Construye la lógica del juego del 3 en raya en el componente game.
Una pista de la función para saber el ganador:
panel = [0,0,0,0,0,0,0,0,0]
hasWin(playerId) {
// -
let bool=(panel[0] == playerId && panel[1] == playerId && panel[2]==playerId);
bool=bool || (panel[3] == playerId && panel[4] == playerId && panel[5]==playerId);
bool=bool || (panel[6] == playerId && panel[7] == playerId && panel[8]==playerId);
// |
bool=bool || (panel[0] == playerId && panel[3] == playerId && panel[6]==playerId);
bool=bool || (panel[1] == playerId && panel[4] == playerId && panel[7]==playerId);
bool=bool || (panel[2] == playerId && panel[5] == playerId && panel[8]==playerId);
// /
bool=bool || (panel[0] == playerId && panel[4] == playerId && panel[8]==playerId);
bool=bool || (panel[2] == playerId && panel[4] == playerId && panel[6]==playerId);
return bool;
}