Acciones asíncronas
` Ya hemos visto como usar middlewares para realizar acciones síncronas. Ahora toca el otro pilar de los middlewares, las acciones asíncronas.
Crear una aplicacion nueva
Creamos una aplicación nueva con create-react-app
y eliminamos todo el código de App.js, App.css, index.css, logo.svg y eliminamos sus referencias.
Importamos los middleware redux-logger
, redux-thunk
y la libreria para peticiones asíncronas axios
.
Así debería quedar nuestro App.js nuevo inicial.
import React from 'react';
import { applyMiddleware, createStore } from 'redux';
import axios from 'axios';
import logger from 'redux-logger';
import thunk from 'redux-thunk';
const reducer = (state = {}, action) => {
return state;
};
const middleware = applyMiddleware(thunk, logger());
const store = createStore(reducer, middleware);
store.subscribe(() => {
console.log('Store has changed', store.getState());
});
store.dispatch({ type: 'FOO' });
class App extends React.Component {
render() {
return (
<div className="App">
Boilerplaite app
</div>
);
}
}
export default App;
Modificar dispatch usando thunk
El middleware redux-thunk nos permite escribir creadores de acciones que devuelven una función en lugar de una acción. El thunk se puede utilizar para retrasar el envío de una acción, o para enviar sólo si se cumple una cierta condición. La función interna recibe los métodos de almacén dispatch y getState como parámetros.
store.dispatch((dispatch) => {
dispatch({ type: 'POSTS_FETCH_START' });
axios
.get('https://jsonplaceholder.typicode.com/posts')
.then((response) => {
dispatch({ type: 'POSTS_FETCH_FINISHED', payload: response.data });
})
.catch((error) => {
dispatch({ type: 'POSTS_FETCH_FAILED', payload: error });
});
});
Modificar el reducer
Puesto que ahora tenemos estados dinámicos, necesitamos inicilizar el estado, ya no puede ser un objeto vacio.
const initialState = {
fetching: false,
fetched: false,
posts: [],
error: null,
};
Y modificaremos el reducer para que atienda las nuevas acciones
const reducer = (state = initialState, action) => {
switch (action.type) {
case 'POSTS_FETCH_START':
return {
...state,
fetching: true,
};
case 'POSTS_FETCH_FINISHED':
return {
...state,
fetching: false,
fetched: true,
posts: action.payload,
};
case 'POSTS_FETCH_FAILED':
return {
...state,
fetching: false,
error: action.payload,
};
default:
return state;
}
};
Ejercicio: Cambiar redux-thunk
por redux-promise-middleware