在使用Redux创建异步Thunk并使用said Thunk作为extraReducer时,我将面临这个问题。
当我像这样指定Return argument、Thunk Argument和ThunkApiConfig时,它会从notificationsAdapter.upsertMany()行的问题标题中抛出错误
export const fetchNotifications = createAsyncThunk<
Notifications,
void,
{ state: RootState }
>("notifications/fetchNotifications", async (_, { getState }) => {
const allNotifications = selectAllNotifications(getState());
const [latestNotification] = allNotifications;
const latestTimestamp = latestNotification ? latestNotification.date : "";
const response = await client.get(
`/fakeApi/notifications?since=${latestTimestamp}`
);
return response.notifications;
});
const notificationsSlice = createSlice({
name: "notifications",
initialState,
reducers: {
allNotificationsRead(state) {
Object.values(state.entities).forEach((notification) => {
notification && (notification.read = true);
});
},
},
extraReducers: (builder) => {
builder.addCase(fetchNotifications.pending, (state) => {
state.status = "loading";
});
builder.addCase(fetchNotifications.rejected, (state, action) => {
state.status = "failed";
state.error = action.error.message as Error;
});
builder.addCase(fetchNotifications.fulfilled, (state, action) => {
state.status = "succeeded";
Object.values(state.entities).forEach((notification) => {
notification && (notification.isNew = !notification.read);
});
notificationsAdapter.upsertMany(state, action.payload);
});
},
});但是,当我从createAsyncThunk中删除类型并断言getState()是RootState(它来自使用export type RootState = ReturnType<typeof store.getState>的商店)时,就没有错误了,所以我不确定我以前设置的值有什么问题。
export const fetchNotifications = createAsyncThunk(
"notifications/fetchNotifications",
async (_, { getState }) => {
const allNotifications = selectAllNotifications(getState() as RootState);
const [latestNotification] = allNotifications;
const latestTimestamp = latestNotification ? latestNotification.date : "";
const response = await client.get(
`/fakeApi/notifications?since=${latestTimestamp}`
);
return response.notifications;
}
);这方面的代码可以找到这里。
发布于 2021-04-03 23:23:22
您必须非常小心地处理as断言,因为如果断言的内容不正确,就会产生问题。例如,您的类型Error是string | null,而action.error.message是string | undefined。当它是undefined时会发生什么
而不是坚持打字,你有正确的类型:
state.error = action.error.message as Error;实际上,您应该通过使用空的聚结来将undefined替换为null,从而执行正确的类型。
state.error = action.error.message ?? null;@Nadia的评论是正确的。upsertMany需要数组Notifications[]或键控对象Record<EntityId, Notifications>。您的fetchNotifications操作正在返回一个通知Notifications。您的client.get响应是any,所以您不会因为返回错误类型而产生任何错误。
当您移除类型时,您不会得到任何错误,因为现在您的fetchNotifications操作返回any。
您希望确保正在返回数组Notifications[]。
在我看来,避免这种错误的最好方法是有一个强类型的client,它可以根据端点返回正确的类型。
interface EndpointMap {
"/fakeApi/notifications": Notifications;
}
interface Client {
getOne<K extends keyof EndpointMap>(
endpoint: K,
id: string
): Promise<EndpointMap[K]>;
getMany<K extends keyof EndpointMap>(
endpoint: K,
args: Record<string, any>
): Promise<EndpointMap[K][]>;
}https://stackoverflow.com/questions/66932277
复制相似问题