我有一个用 typescript 编写的 react hooks 应用程序,其中包含多个 reducer,我将它们与 context API 一起使用。
我需要在 reducer 之间共享错误状态,因为我只需要在应用程序中显示一个错误状态,可以使用errorReducer
.
问题是,我需要从“其他”减速器设置状态的错误部分(“其他”我的意思不是errorReducer
)。
如果我尝试useAsyncReducer
在“其他”减速器中使用 useReducer 钩子(或我自己的钩子)来设置错误,我会得到
错误:无效的挂钩调用。Hooks 只能在函数组件的主体内部调用
,如下所示。
如何在react中的reducer之间共享状态?(请参阅下面的“待办事项:这是我需要的”)。
请注意,我不想使用 redux。
export type Actor = {
_id?: string,
firstName?: string,
lastName?: string,
selectedForDelete?: boolean
}
// Compound state for 3 reducers (activeEntityTypeReducer, actorReducer, errorReducer)
export type State = {
activeEntityType: string,
actors: Actor[],
error: string | null
}
export const EMPTY_INITIAL_STATE: State = {
activeEntityType: EntityType.ACTOR,
actors: [],
error: null
};
// ERROR REDUCER:
export const errorReducer = async (state: string | null, action: ErrorActions) => {
switch (action.type) {
case ErrorActionType.SET_ERROR: {
return action.payload;
}
default:
return state;
}
};
// ACTOR REDUCER:
export const actorReducer = async (state: Actor[], action: ActorActions) => {
// I cannot use here a hook like this because it triggers: "Error: Invalid hook call. Hooks can only be called inside of the body of a function component"
// const { dispatch: dispatchError } = useAsyncReducer(errorReducer, EMPTY_INITIAL_STATE);
switch (action.type) {
//... other actions
case ActorActionType.SEARCH_ACTORS: {
return fetch(
"http://localhost:3000/api/actors?pagesize=100"
).then(response => response.json())
.then(response => response['data']);
/* // TODO: THIS IS WHAT I NEED: continue the above line with a catch inside which I dispatch the error
.catch((error) => dispatchError({
type: ErrorActionType.SET_ERROR,
payload: error
}))
*/
}
default:
return state;
}
};
// MAIN (COMPOSED) REDUCER:
export const mainReducer = async ({ activeEntityType, actors, error }: State,
action: ActiveEntityTypeActions | ActorActions | ErrorActions) => (
{
actors: await actorReducer(actors, action as ActorActions),
activeEntityType: activeEntityTypeReducer(activeEntityType, action as ActiveEntityTypeActions),
// more reducers here and all need to set the error
error: await errorReducer(error, action as ErrorActions)
});