创建侦听所有操作错误的 React 中间件
Creating React middleware that listens for errors on all actions
我正在编写我的第一个自定义中间件,但对正在发生的事情一无所知。我的 objective 是检查是否有任何操作收到网络错误,如果是 console.log 它。
import { Middleware, MiddlewareAPI, Dispatch, Action } from "redux"
export const logger: Middleware = <S>(api: MiddlewareAPI<S>) => (
next: Dispatch<S>
) => <A extends Action>(action: A): A => {
console.log("Before")
const result = next(action)
if (action.type.HTTPStatus) {
console.log("HERE IS AN ERROR")
}
console.log("After", api.getState())
return result
}
action.type.HTTPStatus 不起作用。我一直在尝试根据 action.type 过滤操作,但我不确定该怎么做。似乎我附加到 action.type.whatever 的所有东西都不会破坏任何东西,但也不会做任何事情。下面是一个 API 动作的例子。
export const getTelevisionChannels = (televisionIds: string[]) => async (
dispatch: Dispatch<AppState>
) => {
try {
const response = await API.post(
"/Channels/querys/status",
{ body: JSON.stringify({ televisionIds }) },
true,
dispatch
)
const televisionChannels = await response.json()
televisionChannels.map((televisionChannel: any) =>
dispatch(
getChannelsSuccess(televisionChannel.televisionId, televisionChannel.channels)
)
)
} catch (err) {
dispatch(push("/404"))
console.log(err)
}
}
我确实有一个目标是使用一个单独的 Dispatch 组件来处理这个错误,它有自己的减速器和动作,但首先我需要能够让这个中间件工作。
最近写了一个apiMiddleware,这里是简化版。您想要的是在出现 API 问题时捕获错误,然后分派错误操作 { type: errorType }
。然后你需要一个reducer来处理这些变化。
export default function createApiMiddleware(axios) {
return ({ getState }) => next => action => {
const api = action[CALL_API]
if (!api) {
return next(action)
}
const obj = {}
const { actionPrefix, types, method, host, url, onSuccess, ...props } = api
const prefix = actionPrefix || ''
const [startedType, successType, errorType] = types ? types : ACTION_KEYS.map(v => prefix + v)
next({ type: startedType })
obj.method = method || 'get'
obj.url = host ? (host + url) : url
const onSuccessOps = Object.assign({}, defaultOnSuccess, onSuccess)
const { responseBody } = onSuccessOps
const afterSuccess = (payload) => {
const { customActions } = onSuccessOps
customActions.forEach(type => {
next({ type, payload })
})
}
return axios(
Object.assign(obj, { ...props })
).then(res => {
const payload = responseBody(res)
next({ type: successType, payload })
afterSuccess(payload)
}, err => {
next({ type: errorType, payload: err })
})
}
}
export default function createApiReducer(actionPrefix, options) {
const ops = Object.assign({}, defaultOptions, options)
const initialState = {
data: [],
isLoaded: false,
isLoading: ops.loadOnStart,
error: null,
}
return (state = initialState, action) => {
const custom = ops.customActions[action.type]
if (custom) {
return custom(state)
}
switch (action.type) {
case `${actionPrefix}Loading`:
return {
...state,
isLoading: true,
error: null
}
case `${actionPrefix}Error`:
return {
...state,
isLoading: false,
error: action.payload
}
case `${actionPrefix}Success`:
return {
...state,
isLoading: false,
isLoaded: true,
error: null,
data: action.payload
}
default:
return state
}
}
}
因为你想要一个中间件,所以我把它放在这里作为参考,通常你只想在任何 redux 教科书中为一个 API 分派几个动作。希望这可以帮助。
我正在编写我的第一个自定义中间件,但对正在发生的事情一无所知。我的 objective 是检查是否有任何操作收到网络错误,如果是 console.log 它。
import { Middleware, MiddlewareAPI, Dispatch, Action } from "redux"
export const logger: Middleware = <S>(api: MiddlewareAPI<S>) => (
next: Dispatch<S>
) => <A extends Action>(action: A): A => {
console.log("Before")
const result = next(action)
if (action.type.HTTPStatus) {
console.log("HERE IS AN ERROR")
}
console.log("After", api.getState())
return result
}
action.type.HTTPStatus 不起作用。我一直在尝试根据 action.type 过滤操作,但我不确定该怎么做。似乎我附加到 action.type.whatever 的所有东西都不会破坏任何东西,但也不会做任何事情。下面是一个 API 动作的例子。
export const getTelevisionChannels = (televisionIds: string[]) => async (
dispatch: Dispatch<AppState>
) => {
try {
const response = await API.post(
"/Channels/querys/status",
{ body: JSON.stringify({ televisionIds }) },
true,
dispatch
)
const televisionChannels = await response.json()
televisionChannels.map((televisionChannel: any) =>
dispatch(
getChannelsSuccess(televisionChannel.televisionId, televisionChannel.channels)
)
)
} catch (err) {
dispatch(push("/404"))
console.log(err)
}
}
我确实有一个目标是使用一个单独的 Dispatch 组件来处理这个错误,它有自己的减速器和动作,但首先我需要能够让这个中间件工作。
最近写了一个apiMiddleware,这里是简化版。您想要的是在出现 API 问题时捕获错误,然后分派错误操作 { type: errorType }
。然后你需要一个reducer来处理这些变化。
export default function createApiMiddleware(axios) {
return ({ getState }) => next => action => {
const api = action[CALL_API]
if (!api) {
return next(action)
}
const obj = {}
const { actionPrefix, types, method, host, url, onSuccess, ...props } = api
const prefix = actionPrefix || ''
const [startedType, successType, errorType] = types ? types : ACTION_KEYS.map(v => prefix + v)
next({ type: startedType })
obj.method = method || 'get'
obj.url = host ? (host + url) : url
const onSuccessOps = Object.assign({}, defaultOnSuccess, onSuccess)
const { responseBody } = onSuccessOps
const afterSuccess = (payload) => {
const { customActions } = onSuccessOps
customActions.forEach(type => {
next({ type, payload })
})
}
return axios(
Object.assign(obj, { ...props })
).then(res => {
const payload = responseBody(res)
next({ type: successType, payload })
afterSuccess(payload)
}, err => {
next({ type: errorType, payload: err })
})
}
}
export default function createApiReducer(actionPrefix, options) {
const ops = Object.assign({}, defaultOptions, options)
const initialState = {
data: [],
isLoaded: false,
isLoading: ops.loadOnStart,
error: null,
}
return (state = initialState, action) => {
const custom = ops.customActions[action.type]
if (custom) {
return custom(state)
}
switch (action.type) {
case `${actionPrefix}Loading`:
return {
...state,
isLoading: true,
error: null
}
case `${actionPrefix}Error`:
return {
...state,
isLoading: false,
error: action.payload
}
case `${actionPrefix}Success`:
return {
...state,
isLoading: false,
isLoaded: true,
error: null,
data: action.payload
}
default:
return state
}
}
}
因为你想要一个中间件,所以我把它放在这里作为参考,通常你只想在任何 redux 教科书中为一个 API 分派几个动作。希望这可以帮助。