【全栈React】第21天: Redux中间件
今天,我们在Redux方法中使用Redux中间件来管理我们的代码中的复杂状态变化。 昨天,我们连接的点与Redux,从工作通过归并器,更新行动的创造者,并连接Redux到React组件。 Redux中间件 将解锁更多的权力,我们今天将会触及。 Redux中间件中间件通常指的是软件服务,"粘合在一起" 在现有软件中的独立功能。对于Redux,中间件提供了一个 第三方扩展点,在分发动作和将分发交给归并器之间: [ Action ] [ Middleware ] [ Dispatcher ] [ 动作 ] [ 中间件 ] [ 分发 ] 中间件的示例包括日志记录、崩溃报告、路由、处理异步请求等。 让我们来处理异步请求,就像对服务器的 HTTP 调用那样。中间件是一个很好的地方。 我们中间件api我们将实现一些中间件,它将代表我们处理异步请求。 中间件位于动作和归并器之间。它可以监听所有的调度和执行代码与行动和当前状态的细节。中间件提供了一个强大的抽象。让我们来看看如何使用它来管理我们自己的。 继续我们从昨天开始的 在我们做得太多之前,让我们从 First,let's pull the work into it's own file in
import * as types from './types'; export const initialState = { currentTime: new Date().toString(),} export const reducer = (state = initialState,action) => { switch(action.type) { case types.FETCH_NEW_TIME: return { ...state,currentTime: action.payload} default: return state; } } export default reducer 根归并器用我们的 import { combineReducers } from 'redux'; import * as currentUser from './currentUser'; import * as currentTime from './currentTime'; export const rootReducer = combineReducers({ currentTime: currentTime.reducer,currentUser: currentUser.reducer,}) export const initialState = { currentTime: currentTime.initialState,currentUser: currentUser.initialState,} export default rootReducer 最后,让我们更新 import { rootReducer,initialState } from './reducers' // ... export const configureStore = () => { const store = createStore( rootReducer,initialState,); return store; } 返回到中间件中间件基本上是一个接受 可能是最简单的中间件让我们构建最小的中间件,我们可能能够准确地理解到底发生了什么,以及如何将它添加到我们的栈中。 让我们创建我们的第一个中间件。 现在,中间件的签名看起来像这样: const loggingMiddleware = (store) => (next) => (action) => { // Our middleware } 对这个中间件的事情很迷惑?别担心,我们都是第一次看到它。让我们把它剥离回来一点点,拆解发生了什么事。上面的 const loggingMiddleware = function(store) { // Called when calling applyMiddleware so // our middleware can have access to the store return function(next) { // next is the following action to be run // after this middleware return function(action) { // finally,this is where our logic lives for // our middleware. } } } 我们不需要担心 怎么 被调用,只是它确实得到了这个顺序调用。让我们增强我们的 const loggingMiddleware = (store) => (next) => (action) => { // Our middleware console.log(`Redux Log:`,action) // call the next function next(action); } Our middleware causes our store to,when every time an action is called,we'll get a 为了将中间件应用到我们的栈中,我们将用这个恰当命名的 import { createStore,applyMiddleware } from 'redux'; 对于 应用 中间件,我们可以在 const store = createStore( rootReducer,applyMiddleware( apiMiddleware,loggingMiddleware,) ); 现在我们的中间件已经到位。在浏览器中打开控制台以查看此演示所调用的所有动作。尝试单击打开控制台的 正如我们所看到的,中间件使我们能够在我们的Redux动作调用链中插入一个函数。在该函数中,我们可以访问该动作、状态,而且我们还能够分发其他动作。 我们希望编写一个可以处理 API 请求的中间件函数。我们可以编写一个中间件函数,它只侦听与 API 请求对应的动作。我们的中间件可以 "监视" 具有特殊标记的动作。例如,我们可以有一个 const apiMiddleware = store => next => action => { if (!action.meta || action.meta.type !== 'api') { return next(action); } // This is an api request } 如果某个动作有一个带有 让我们转换我们的 让我们把这个请求的 URL 传递给我们的 const host = 'https://andthetimeis.com' export const fetchNewTime = ({ timezone = 'pst',str='now'}) => ({ type: types.FETCH_NEW_TIME,payload: new Date().toString(),meta: { type: 'api',url: host + '/' + timezone + '/' + str + '.json' } }) 当我们按下按钮更新的时间,我们的 我们的 API 中间件需要采取的步骤:
让我们采取这按步就班的步骤。首先,关闭 const apiMiddleware = store => next => action => { if (!action.meta || action.meta.type !== 'api') { return next(action); } // This is an api request // Find the request URL and compose request options from meta const {url} = action.meta; const fetchOptions = Object.assign({},action.meta); // Make the request fetch(url,fetchOptions) // convert the response to json .then(resp => resp.json()) .then(json => { // respond back to the user // by dispatching the original action without // the meta object let newAction = Object.assign({},action,{ payload: json.dateString }); delete newAction.meta; store.dispatch(newAction); }) } export default apiMiddleware 我们有几个选项,我们如何回复到Redux链中的用户。就个人而言,我们更喜欢用相同的类型响应请求被激发,而没有 这样,我们不需要改变我们的Redux归并器来管理响应任何不同的,如果我们没有提出要求。 我们也不限于一个单一的响应。假设我们的用户在请求完成时通过了 const apiMiddleware = store => next => action => { if (!action.meta || action.meta.type !== 'api') { return next(action); } // This is an api request // Find the request URL and compose request options from meta const {url} = action.meta; const fetchOptions = Object.assign({},fetchOptions) // convert the response to json .then(resp => resp.json()) .then(json => { if (typeof action.meta.onSuccess === 'function') { action.meta.onSuccess(json); } return json; // For the next promise in the chain }) .then(json => { // respond back to the user // by dispatching the original action without // the meta object let newAction = Object.assign({},{ payload: json.dateString }); delete newAction.meta; store.dispatch(newAction); }) } 这里的可能性几乎是无止境的。让我们添加 import { createStore,applyMiddleware } from 'redux'; import { rootReducer,initialState } from './reducers' import loggingMiddleware from './loggingMiddleware'; import apiMiddleware from './apiMiddleware'; export const configureStore = () => { const store = createStore( rootReducer,) ); return store; } export default configureStore; 请注意,我们不必更改视图的 _任意_代码 以更新数据在状态树中的填充方式。很漂亮吧? 这个中间件非常简单,但它是构建它的良好基础。您是否可以考虑如何实现缓存服务,以便我们不需要对已有的数据进行请求?如何让一个跟踪挂起的请求,这样我们就可以为未完成的请求显示一个微调框? 太棒了!现在我们真的是Redux忍者。我们已经征服了Redux大山,并准备继续下一步的行动。在我们去之前,但是..。我们已经完成了3周!
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |