Thunk. Какое странное слово.

«В компьютерном программировании преобразователь - это подпрограмма, используемая для введения дополнительных вычислений в другую подпрограмму. Преобразователи в основном используются для задержки вычисления до тех пор, пока не потребуется его результат, или для вставки операций в начало или конец другой подпрограммы ». - Википедия

Проще говоря, преобразователь относится к последовательности инструкций, встроенных в другую последовательность инструкций посредством возврата функции из другой функции! Зачем нам это делать ?! Ну, как объяснялось выше, иногда нам нужно отложить или изменить ход нашей программы или вычислений. Следовательно, чем сложнее наши приложения, тем дольше мы выполняем или чем активнее будут задействованы наши функции, тем выше вероятность, что мы захотим делать такие вещи.

В качестве примера, вот как я реализую Thunk в моем проекте React Redux Storyteller. Используя redux-thunk *, я добавил свойство загрузки в свои истории, чтобы загружать и отображать сообщение о загрузке во время загрузки историй.

* Промежуточное ПО Redux, которое позволяет пользователям возвращать функцию в функции создателя действия для выполнения асинхронных веб-запросов данных в Redux.

Когда StoriesContainer монтируется (когда пользователь впервые посещает Storyteller или после успешного добавления истории):

  1. Вызывается функция создания действия fetchStories ().
  2. Непосредственно после вызова fetchStories () возвращает функцию (return ()) с аргументом функции диспетчеризации магазина - это позволяет нам возвращать несколько действий вместо того, чтобы возвращать простой объект JavaScript.
  3. Первое отправленное действие указывает состояние загрузки (мы делаем запрос к API).
  4. Затем вызывается метод fetch (), возвращающий обещание.
  5. Наконец, когда это обещание разрешается, наше последнее действие ТОГДА отправляется. Мы отправляем полученные данные соответствующему редуктору историй. Если loading истинно, мы можем отобразить сообщение о загрузке в JSX.
class StoriesContainer extends Component {
componentDidMount() {
 this.props.fetchStories();
 this.props.fetchTopStory();
}
...
}

функция создания действия fetchStories ():

export const fetchStories = () => {
    return (dispatch) => {
        dispatch({ type: 'LOADING_STORIES' });
        fetch('http://localhost:3000/stories')
            .then(response => response.json())
            .then(stories => dispatch({ type: 'FETCH_STORIES',         payload: stories }));
    };
}

Редуктор:

export const storiesReducer = (state = { stories: [], loading: false }, action) => {
    switch (action.type) {
        case 'FETCH_STORIES':
            return {
                stories: action.payload,
                loading: false
            }

        case 'LOADING_STORIES':
            return {
                ...state,
                stories: [...state.stories],
                loading: true
            }

        ...

        default:
            return state;
    }
}

Чтобы отобразить сообщение о загрузке:

class StoriesContainer extends Component {
componentDidMount() {
  this.props.fetchStories();
  this.props.fetchTopStory();
}

render() {
  if(this.props.loading) {
    return <div>LOADING...</div>;
  }
  return (
    ...
  );
}

const mapStateToProps = state => {
  return {
    topStory: state.stories.story,
    stories: state.stories,
    user: state.auth.currentUser,
    loading: state.stories.loading 
  }
}

Поскольку запросы на выборку в JavaScript являются асинхронными, без преобразователя, dispatch ({type: 'FETCH_STORIES', payload: stories}) начнет выполняться до того, как веб-запрос (наше обещание) будет разрешен, и мы получим ответ, который мы действительно можем работать (разбирать в JSON). Ой!

Кроме того, как мы все хорошо знаем, получение данных иногда может занять некоторое время, и НИКТО не любит смотреть на пустой экран, не зная, что происходит во время ожидания. Thunk позволяет нам использовать это промежуточное состояние или состояние загрузки до тех пор, пока наши данные не будут извлечены, состояние нашего хранилища не будет обновлено (через редуктор) и, наконец, наш компонент не отобразит желаемую информацию о состоянии.

Убежденный? Прохладный! Вот как установить и использовать пакет NPM Redux Thunk:

  • В вашей среде IDE выполните следующую команду: npm install - save redux-thunk
  • Затем в index.js импортируйте applyMiddleware () из redux вместе с преобразователем из пакета redux-thunk и передайте applyMiddleware (thunk) в качестве аргумента createStore.
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
...
 
const store = createStore(rootReducer, applyMiddleware(thunk));
 
...

И все готово!

Thunk за чтение!