Быстрый старт Redux-thunk

внешний интерфейс исходный код React.js Redux

предисловие

Недавно я завершил свою выпускную защиту. Мой выпускной контент представляет собой веб-приложение, похожее на Instagram, разработанное на основе стека технологий серии React.Нажмите здесь, чтобы увидеть. После разработки я с удивлением обнаружил: Эй, я слышал раньше, что есть компания под названиемredux-thunkвещи, почему я не использовал их? Бизнес-сценарий слишком прост? Так что я, вероятно, сделал некоторые исследования. .

Основное введение в концепции

Базовое введение в redux-thunk, возможно, вы можете сначала взглянутьstackoverflowприведенное выше введение. Личное понимание: redux-thunk переписывает API диспетчеризации так, чтобы у него была возможность принимать функцию в качестве параметра, чтобы добиться эффекта промежуточного ПО, то есть в процессе диспетчеризации редукса action=>reducer=>store, после того, как действие инициировано, достигните точки расширения перед редюсером и добавьте связанные операции, такие как возникновение запросов, информация журнала и т. д.

фактическое использование

Возьмем пример добавления асинхронных запросов в процесс редукции в моем завершенном проекте, чтобы реализовать часть кода для динамической функции Like:

  • Я изначально написал это
//from action.js
const LIKE = (id) => ({
     type: "LIKE",
     id:id
})

reqLike({id:id}).then(res =>{ dispatch(LIKE(id))})

Как видите, я отправляю действие в функции обратного вызова после запроса на синхронизацию состояния в хранилище избыточности.

  • После добавления redux-thunk я написал следующее:
//from action.js
const LIKE = (id) => {
    return function (dispatch,getState) {
        reqLike({id:id}).then(res =>{ 
            dispatch({
                type: "LIKE",
                id:id
            })
        })
    }
}

dispatch(LIKE(id))

После изменения с функционального уровня между ними нет никакой разницы, и оба они могут удовлетворить потребности бизнес-сценариев. Но помимо этого мы можем найти:

  • 1. Параметр, принимаемый диспетчером, меняется с PlainObject на функцию
  • 2. Подключаем асинхронную операцию запроса от редукции процесса диспетчерского действия в процесс, который вроде быАсинхронные операции связаны с этим процессом, будь то логически понятое (это очень промежуточное ПО!) или разработка и сопровождение кода проекта (различение асинхронных и синхронных процессов управления состоянием для управления обслуживанием) является большим улучшением
  • 3. Если в проекте есть много мест, где нужно реализовать подобную функцию, мы можем сэкономить много избыточного кода, не размещая везде reqLike(id).then(...) на внешнем уровне диспетчеризации.

Анализ исходного кода

После понимания основных концепций и приложений redux-thunk давайте взглянем на исходный код, чтобы углубить наше понимание.Исходный код очень деликатный.

Сначала посмотрите часть applyMiddleware в исходном коде redux.После передачи thunk в качестве параметра мы напрямую возвращаем функцию, которая передается в качестве энхансера функции createStore в исходном коде redux.

export default function applyMiddleware(...middlewares) {
  //这个返回函数就是enhancer
  return (createStore) => (reducer, preloadedState, enhancer) => {
    const store = createStore(reducer, preloadedState, enhancer)
    let dispatch = store.dispatch
    let chain = []

    const middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    }
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

В Redux источником функции Createstore Enhancer выполняется, прохождение параметров Createstore, и немедленно выполняет функцию возврата, прохождение редуктора и предварительной нагрузки.

if (typeof enhancer !== 'undefined') {
    if (typeof enhancer !== 'function') {
      throw new Error('Expected the enhancer to be a function.')
    }
    
    return enhancer(createStore)(reducer, preloadedState)
}

Затем мы вводим ключевые части applyMiddleware и thunk.Начальный (...middlewares) параметр, принятый applyMiddleware выше, на самом деле является thunk, thunk будет выполняться, а параметры getState и dispatch передаются.

//传入到thunk的参数
const middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    }
//在map中执行thunk
chain = middlewares.map(middleware =>middleware(middlewareAPI))
//重新改写dispatch
dispatch = compose(...chain)(store.dispatch)

Итак, что за цепочка выше, мы наконец-то можем взглянуть на исходный код redux-thunk!

function createThunkMiddleware(extraArgument) {
  return function (_ref) {
    var dispatch = _ref.dispatch,
        getState = _ref.getState;
    //这里返回的函数就是chain
    return function (next) {
    //这里返回的函数就是改写的dispatch
      return function (action) {
        if (typeof action === 'function') {
          return action(dispatch, getState, extraArgument);
        }

        return next(action);
      };
    };
  };
}

var thunk = createThunkMiddleware();

Из исходного кода видно, что цепочка — это анонимная функция с формальным параметром next.Что касается компоновки, то она просто непрерывно передает возвращаемое значение каждой функции следующей исполнительной функции, а затем последовательно выполняет все входящие функции. , В комментарии ясно сказано:For example, compose(f, g, h) is identical to doing (...args) => f(g(h(...args))).

Цепочка, которую мы имеем здесь, — это просто функция, поэтому очень просто выполнить цепочку и передать store.dispatch как следующую.

Затем введите последний шаг, перепишите диспетчеризацию и, наконец, станьте:

function (action) {
    if (typeof action === 'function') {
      return action(dispatch, getState, extraArgument);
    }
    //next为之前传入的store.dispatch,即改写前的dispatch
    return next(action);
};

Если переданный параметр является функцией, выполните функцию. В противном случае диспетчеризация (PlainObject) такая же, как и раньше.

Суммировать

redux-thunk реализует объединение связанных асинхронных процессов в процесс redux, реализует функцию промежуточного программного обеспечения, а также облегчает разработку и сопровождение проекта и позволяет избежать избыточного кода. Способ добиться этого — переписать диспетчерский API в редукции, чтобы он мог принимать функцию в качестве параметра в дополнение к PlainObject.