redux-thunk
W sekcji poświęconej akcjom i kreatorom akcji poznaliśmy kilka ograniczeń:
- kreatory akcji muszą być synchroniczne,
- kreatory akcji nie mają dostępu do stanu Reduxa
Oznacza to ,ze nie możemy używać kreatorów np. do pobrania danych z API i przekazania ich do Reduxa; wszelkie tego typu operacje musiały by mieć miejsce w cyklu życia komponentu. Nieco komplikuje to działanie Reduxa:
- Komponent rozpoczyna pobieranie danych
- Komponent przekazuje dane do akcji
- Akcja aktualizuje Redux
- Komponent dostaje dane jako props
Niestety, w ten sposób znów "wiążemy" nasz komponent UI z logiką aplikacji. Aby temu zapobiec możemy użyć middleware redux-thunk. Uzbrojeni w wiedzę nt. działania middleware zacznijmy od analizy kodu źródłowego:
const thunkMiddleware = ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState);
}
return next(action);
};
Kod został nieznacznie uproszczony na potrzeby przykładu.
Przykładowy thunk
Jak widać, middleware wykonuje tylko jedną prostą operację: jeżeli wartość przekazana do dispatch() jest funkcją, zostaje ona przechwycona (nie jest wywołane next(action)) i wywołana z 2 argumentami: dispatch i getState. Dzięki temu możemy tworzyć "thunki"
const getDataFromApi = () => {
// Nasz action creator nie zwraca akcji, ale funkcję
return function getData(dispatch) {
// Funkcja zostaje następnie wywołana przez redux-thunk i otrzymuje
// dostęp do dispatch i getStore. Wykonujemy zapytanie do API.
makeApiCall().then(data => {
// I kiedy zostanie ono zakończone, dispatchujemy właściwą akcję
dispatch({
type: 'DATA_LOADED',
payload: data
});
}).catch(error => {
dispatch({
type: 'DATA_LOAD_ERROR',
error: true,
payload: error
});
});
}
};
const mapDispatchToProps = {
getDataFromApi
};
W tym momencie przebieg danych jest następujący:
- Komponent wywołuje
props.getDataFromApi() - Do Reduxa dispatchowana jest funkcja
getData - Middleware
redux-thunksprawdza, że typemactionjestfunction; wywołuje funkcję z argumentemdispatchigetState(który ignorujemy) i przerywa łańcuch - Funkcja
getDatazostaje wywołana i wykonuje zapytanie do api (Promise) makeApiCallwykonuje się poprawnie (lub z błędem) i wywołujedispatchz właściwą akcją- Middleware
redux-thunksprawdz, że typemactionNIE jestfunctioni po prostu przekazuje ją do kolejnego middleware i dalej reducera - Komponent ulega przerenderowaniu z nowymi danymi