Async actions con Redux & Redux-thunk

Redux es una super librería para manejar nuestro estado en nuestras aplicaciones enviando acciones y modificando a placer nuestro estado, la simpleza de redux no permite que esta maneje acciones asíncronas y por ende es bueno utilizar algún middleware para llevar acabo dicho comportamiento, entre las opciones están redux-thunk, la cual es super simple de implementar y manejar.

Con este tutorial estoy asumiendo que conocen redux y tiene un proyecto corriendo con el mismo

Para instalar la librería simplemente ejecutar una de estas acciones:

yarn add redux-thunk

npm install redux-thunk

aplicar el middleware a nuestra redux ‘store‘:

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';

const reducer = (state={}, action) => {
    return state;
};

const store = createStore(reducer, applyMiddleWare(thunk));

Una vez hecho esto tenemos nuestro store listo para recibir “async actions”, este middleware simplemente lo que permite que le podamos hacer “dispatch” a funciones y no a objetos planos como estamos acostumbrados.

Action con objeto plano

const acccion = store.dispatch({type:'SIMPLE_ACCION'});

console.log(accion);

Async Acción:

const acccion = store.dispatch((dispatch) => {
    dispatch({type: 'SIMPLE_ACCION'})
});

console.log(accion);

Si ejecutaron ambas porciones de código se darán cuenta que el método dispatch simplemente retorna lo mismo que le pasamos, y en caso de las acciones async simplemente es una función, ahora el chiste de thunk esta en que tomara enviara un parámetro con la función dispatch para que sea uno mismo que haga el dispatch desde adentro de nuestra función, dicho dispatch sera el mismo que utilizamos previamente que es simplemente enviarle un objeto plano.

Ejemplo completo:

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';

const reducer = (state={}, action) => {
    return state;
};

const store = createStore(reducer, applyMiddleware(thunk));

store.subscribe(() => {
  console.log('Estado', store.getState());
});

store.dispatch((dispatch) => {
    dispatch({type: 'SIMPLE_ACCION1'})
});

store.dispatch((dispatch) => {
    dispatch({type: 'SIMPLE_ACCION2'})
});

Ese seria un ejemplo completo y super básico de como usar redux-thunk, ahora he aquí un ejemplo un poco mas completo e incluyendo una petición http en el cual estaríamos obteniendo una lista de monedas de cambio.

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';

const reducer = (state={}, action) => {
    swtich(action.type){
        CASE 'SIMPLE_ACCION1':
            return state;
        case 'SIMPLE_ACCION2'
            return {...state, data: action.payload};
    }
    return state;
};

const store = createStore(reducer, applyMiddleware(thunk));

store.subscribe(() => {
  console.log('Estado', store.getState());
});

store.dispatch((dispatch) => {
    dispatch({type: 'SIMPLE_ACCION1'})
});

store.dispatch((dispatch) => {
    return fetch('https://api.fixer.io/latest?base=EUR')
            .then((response) => response.json())
            .then((data) => {
                dispatch({type: 'SIMPLE_ACCION2', payload: data})  
            })
});

Ya nuestro ejemplo completo, con respecto a la “Promesa” esta puede ser trabajada desde dentro de la acción como desde fuera, en caso de querer trabajarla desde fuera podríamos tener algo como esto:

store.dispatch((dispatch) => {
    return fetch('https://api.fixer.io/latest?base=EUR');
}).then((response) => response.json())
.then((data) => {
      store.dispatch({type: 'SIMPLE_ACCION2', payload: data})  
});

Solo recordar que el método dispatch retorna lo mismo que le pasamos y en este caso dentro de nuestra acción estamos retornando una Promesa y el lo que estamos haciendo fuera trabajando con esta.

Ejemplo completo en vivo:

Referencias

Api Monedas de cambio
Redux-Thunk
Redux

Share on Google+Share on LinkedInShare on RedditShare on TumblrTweet about this on TwitterShare on Facebook
  • EvelynHernandezR

    Cómo lo harías cuando tienes mapDispatchToProps y mapStateToProps? Gracias.

    • Luis Alberto Romero Calderon

      Te refires a como se puede enviar el async request desde mapDispatchToProps? Si es eso, el resultado es el mismo, solo tiene que hacer tu maping de tu función y llamarla.


      const mapDispatchToProps = (dispatch) => {
      return {
      action1: () => {
      fetchData(dispatch)
      }
      }
      }

      Y en tu componente llamar dicha funcion


      Execute From dispatch to props

      • EvelynHernandezR

        Yap, probaré. Gracias por tu pronta respuesta 🙂

        • Luis Alberto Romero Calderon

          No hay de que, encantado de ayudar.

    • Luis Alberto Romero Calderon

      Tambien debes tener en mente que cuando implementar mapDispatchToProps ya no tienes disponible this.props.dispatch en tu componente, debes de agregarlo explicitamente.