
¿Qué es ?
Un contenedor predecible del estado global de una aplicación en Javascript.
Basada en la arquitectura Flux de Facebook. Pero más sencilla.

¿Pero Redux no es parte de ?
No. Redux es una libería externa.
Puedes usarlo combinado con React, o cualquier otra librería de vistas. Sólo ocupa 2kB y no tiene dependencias.

¿Entonces por qué se asocian tanto los dos términos?
Redux es la librería más elegida en proyectos de React a la hora de abordar el problema del estado de la aplicación pero no es la única.

Conceptos básicos

El estado de tu aplicación se describe como un simple objeto.

Conceptos básicos

Conceptos básicos

{
todos: [{
text: 'Comer',
completed: true
}, {
text: 'Hacer ejercicio',
completed: false
}],
visibilityFilter: 'SHOW_ALL'
}
Estado de la aplicación
El estado es global y puedes recuperarlo desde cualquier parte de tu vista.

Conceptos básicos

Conceptos básicos

{
todos: [{
text: 'Comer',
completed: true
}, {
text: 'Hacer ejercicio',
completed: false
}],
visibilityFilter: 'SHOW_ALL'
}
Estado global
No puedes modificar el estado, tienes que crear uno nuevo a partir del anterior según la acción que hagas.

Conceptos básicos

Conceptos básicos
{
type: 'ADD_TODO',
text: 'Ir a nadar a la piscina'
}

{
type: 'TOGGLE_TODO',
index: 1
}

Acción
Acción
Los 3 principios

1. Única fuente de la verdad
Todo el estado de tu aplicación esta contenido en un único store

Los 3 principios
2. El estado es de sólo lectura (inmutable)
La única forma de modificar el estado es emitir una action que indique que cambió

Los 3 principios
3. Los cambios se realizan con funciones puras.
Para controlar como el store es modificado por las acciones se usan reducers puros

Los 3 principios
El diagrama


Store
View
subscribe
Actions
dispatch
Reducers
El diagrama
Glosario

Actions
Las Actions son objetos de Javascript que tienen una propiedad "type" que indica el tipo de acción. Pueden contener otras propiedades que sirven como "payload" para poder realizar la acción.
{
type: 'ADD_TODO',
text: 'Aprender Redux'
}
Action Creators
Funciones puras que devuelven Actions. Son útiles para evitar inconsistencias en el código y tener que escribir los objetos a mano.
// esta función es un ActionCreator,
// ya que devuelve un objeto que es un Action
function addTodo(text) {
return {
type: 'ADD_TODO',
payload: {
text,
},
}
}
Reducers
Función pura que recibe el estado anterior y la acción y, a partir de ellas, crea un nuevo estado de la aplicación.
(previousState, action) => nextState
function todoApp(state = initialState, action) {
switch (action.type) {
case ADD_TODO:
return Object.assign({}, state, {
todos: [
...state.todos,
{
text: action.text,
completed: false
}
]
})
default:
return state
}
}
Store
Almacena el estado global de la aplicación. Permite que el estado sea leído, que te puedas suscribir a sus cambios y, lo más importante, que envíes acciones para crear un nuevo estado global.
// cargamos la función para crear un store
import { createStore } from 'redux'
// cargamos nuestros reducers
import reducers from './reducers'
// creamos el store
const store = createStore(reducers)
Pequeños ejemplos

Crear tu primera store y tu primer reducer
// archivo: store.js
// importamos el método createStore desde redux
import { createStore } from 'redux'
// creamos nuestro reducer
function todos(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return state.concat([action.text])
default:
return state
}
}
// creamos la store, pasándole el reducer
const store = createStore(todos)
// exportamos la store
export default store
Obteniendo el state
actual de la store
import store from './store.js';
// muestra el estado global actual de la aplicación
console.log(store.getState());
Suscribiéndote a los cambios de la store
import store from './store.js';
// al suscribirte a la store, te devuelve
// una función para ejecutarla y desuscribirte más tarde
const unsubscribe = store.subscribe(() => {
// esta función se ejecuta cuando haya una actualización en el state
console.log(store.getState())
// podríamos aquí actualizar nuestra aplicación con la nueva info
const { usuario } = store.getState()
document.getElementById('usuario').innerHTML = usuario
});
// podríamos usar el método unsubscribe más tarde
// para eliminar la suscripción a la store
document.getElementById('cerrar').addEventListener('click', () => unsubscribe())
Enviando actions para actualizar la store
import store from './store.js';
// Esto envía una acción a la store y actualizará
// el estado usando el reducer que hayas programado
store.dispatch({
type: 'ADD_TODO',
text: 'Aprender React con @midudev'
})
Enviando actions para actualizar la store
import store from './store.js';
import { addTodo } from './actions'
/** Importamos esta función de la anterior línea
function addTodo(text) {
return {
type: 'ADD_TODO',
payload: {
text,
},
}
**/
// Esto envía una acción a la store y actualizará
// el estado usando el reducer que hayas programado
// Esta vez usando un ActionCreator
store.dispatch(addTodo('Aprender React con @midudev'))
Ejemplo práctico


Usando
Redux en React
react-redux
Librería que facilita la conexión de React con Redux gracias a algunas utilidades que ofrece.
# instalando la dependencia en nuestro proyecto
npm install --save react-redux

react-redux
- Evitar la gestión manual de tener que pasar la store a todos nuestros componentes
- Leer el estado global desde cualquier lugar de nuestro árbol de elementos
- Llamar a acciones desde cualquier componente

react-redux

Contenedor / Contenido
Patrón
Contenedor - Contenido
react-redux sigue el patrón de contenedor-contenido de React. Esto es, separar los componentes presentacionales y de contenedor.

Patrón
Contenedor-Contenido
¡Si no tienes claro el concepto puedes volver al curso a revisarlo!


API de
react-redux
connect()
API

<Provider />
react-redux nos proporciona dos utilidades para crear la conexión entre Redux y nuestra aplicación de React de forma sencilla:
connect([mapStateToProps], [mapDispatchToProps])
API

Sirve para conectar un componente de React a la store de Redux.
Devuelve una función que recibe como parámetro el componente que queremos conectar.
connect([mapStateToProps], [mapDispatchToProps])
API

mapStateToProps:
Función que devuelve el trozo de estado al que queremos que el componente se suscriba. Es opcional. Si no se indica, el componente no se suscribirá a la store.
// recibe dos parámetros:
// [state] el estado global actual
// [ownProps] las props que recibe el componente
const mapStateToProps = (state, ownProps) => {
// en este caso, el componente recibirá "counter" como prop
return { counter: state.counter }
}
connect([mapStateToProps], [mapDispatchToProps])
API

mapDispatchToProps:
Función que devuelve las acciones que podrá despachar nuestro componente a la store. Es la única forma cómo podremos generar una actualización del state de la store.
// recibe dos parámetros:
// [dispatch] método para llamar a las actions
// [ownProps] las props que ha recibido el componente
const mapDispatchToProps = (dispatch, ownProps) => {
// nombre de las props para ejecutar y llamar a una action
return {
increment: () => dispatch({ type: 'INCREMENT' }),
decrement: () => dispatch({ type: 'DECREMENT' }),
reset: () => dispatch({ type: 'RESET' })
}
}
connect([mapStateToProps], [mapDispatchToProps])
API

const mapStateToProps = (state, ownProps) => {
// en este caso, el componente recibirá "counter" como prop
return { counter: state.counter }
}
const mapDispatchToProps = (dispatch, ownProps) => {
// nombre de las props para ejecutar y llamar a una action
return {
increment: () => dispatch({ type: 'INCREMENT' }),
decrement: () => dispatch({ type: 'DECREMENT' }),
reset: () => dispatch({ type: 'RESET' })
}
}
const createConnect = connect(
mapStateToProps,
mapDispatchToProps
)
const ComponentWithConnectionToRedux = createConnect(Counter)
export default ComponentWithConnectionToRedux
<Provider store>
API

Hace que la store esté disponible en todo nuestro árbol de elementos. Tendremos que envolver nuestra aplicación con este componente para poder utilizar el método connect en cualquier descendiente.
<Provider store={store}>
API

import {counterReducers} from './reducers'
import Counter from './containers/Counter'
const store = createStore(counterReducers)
ReactDOM.render(
<Provider store={store}>
<Counter />
</Provider>,
document.getElementById('root')
)

Ejemplo práctico
Aprendiendo React - ¿Qué es Redux?
By Miguel Angel Durán García
Aprendiendo React - ¿Qué es Redux?
- 577