предисловие
Недавно я завершил свою выпускную защиту. Мой выпускной контент представляет собой веб-приложение, похожее на 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.