Thunk-redux (санка)
redux-thunk («санка») – это функция, позволяющая выполнять несколько асинхроннных операций. Её можно диспатчить в store, где она сама потом диспатчит в него экшены.
Функцию thunk запускает сам store (redux), куда мы ее и диспатчим. Точнее ее запускает «прослойка» thunk midleware, которую нужно установить между store и редьюсерами. Эта прослойка пропускает экшены дальше в редьюсеры, а функцию thunk она «распаковывает» – хранящиеся в ней экшны снова направляет в storeа, а другие санки (если они есть внутри этой санки) тоже «распапковываются» и так циклами, пока все распакованые экшены передадутся в редьюсеры.
Чем санки полезны?
Санки дают возможность избежать общения UI с DAL, а также передавать несколько экшенов сразу и выполнять асинхронные операции.
Установка thunk-redux
npm i redux-thunk
Применение
- applyMiddleware – это предложенный библиотекой redux способ добавления усилитей, т.е. различных Middleware. Middleware – это всегда функция, которые обычно возвращают функцию, если только целью middleware не является прервать цепочку вызовов. В файле redux-store импортируем applyMiddleware из redux и наш «усилитель» – промежуточный уровень (прокладку) thunkMiddleware между store и reducers:
import { createStore, combineReducers, applyMiddleware } from "redux"; import thunkMiddleware from 'redux-thunk';
- Добавляем функцию applyMiddleware с параметром thunkMiddleware туда, где мы объявляли store с редьюсерами, т.е. параметром к функции createStore. Получается вот так:
let store = createStore(reducers, applyMiddleware(thunkMiddleware));
- В файле reducer нужной компоненты (например, users-reducer.js) создаем и экспортируем саму санку, что напоминает работу с экшн-криэйтерами:
export const getUsersThunkCreator = (currentPage, pageSize) => { return (dispatch) => { dispatch (toogleIsFetching(true)); usersAPI.getUsers(currentPage, pageSize).then(data => { dispatch(toogleIsFetching(false)); dispatch(setUsers(data.items)); dispatch(setTotalUsersCount(data.totalCount)); }); } }
- В контейнерной компоненте в connect закидываем эту санку рядом с экшн-криэйтерами, например:
export default connect (mapStateToProps, {follow, unfollow, setUsers, getUsersThunkCreator}) (UsersContainer);
- Вызываем внутри контейнерной компоненты из пропсов колбек санки. Например, внутри componentDidMount и дальше в коде (конечно же, еще и экспортируем эту сверху функцию сверху):
class UsersContainer extends React.Component { componentDidMount() { this.props.getUsers(this.props.currentPage, this.props.pageSize); } onPageChanged = (pageNumber) => { this.props.getUsers(pageNumber, this.props.pageSize); } render() { .......
Само название функции санок делается более простым (в даном случае можно просто getUsers), а здесь оно более длинное для облегчения понимания.