使用 Redux 工具包可观察到的 Redux 中未触发 Epics
Epics not triggering in Redux observable with Redux toolkit
我尝试按照文档进行操作,这就是我所做的
middleware/index.ts
import { combineEpics } from "redux-observable";
import userEpic from "./userEpic";
export const rootEpic = combineEpics(
userEpic,
);
store.ts
import { configureStore } from "@reduxjs/toolkit";
import { createEpicMiddleware } from "redux-observable";
import { rootEpic } from "../middleware";
import userReducer from "./reducers/userSlice";
const rootReducer = {
user: userReducer,
};
const epicMiddleware = createEpicMiddleware();
export const store = configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(epicMiddleware),
});
epicMiddleware.run(rootEpic);
export type RootStateType = ReturnType<typeof store.getState>;
export type AppDispatchType = typeof store.dispatch;
export default store;
actions.ts
export const LOGIN_USER = "LOGIN_USER";
export const loginUser = () => {
return {
type: LOGIN_USER,
} as const;
};
export type LoginUserAction = ReturnType<typeof loginUser>;
userEpic.ts(这是 API 调用的位置,但我这样做只是为了测试它是否有效)
import { Action } from "@reduxjs/toolkit";
import { Observable } from "rxjs";
import { combineEpics, ofType } from "redux-observable";
import { LOGIN_USER } from "./actions";
import { map } from "rxjs/operators";
import { setUserData } from "../../redux/reducers/userSlice";
const fetchUserEpic = (action$: Observable<Action>) => {
return action$.pipe(
ofType(LOGIN_USER),
map(() =>
setUserData({
id: 12,
name: "test",
surname: "test",
username: "test",
refreshToken: "test",
accessToken: "test",
})
)
);
};
export default combineEpics(fetchUserEpic);
userSlice.ts
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { FetchStatus } from "../../modules/types";
import { RootStateType } from "../store";
type UserType = {
id: number;
name: string;
surname: string;
username: string;
refreshToken: string;
accessToken: string;
};
type UserStateType = {
user: UserType | null;
userFetchStatus: FetchStatus;
};
const initialUserState: UserStateType = {
user: null,
userFetchStatus: FetchStatus.success,
};
export const userSlice = createSlice({
name: "user",
initialState: initialUserState,
reducers: {
setUserData: (state, action: PayloadAction<UserType>) => {
state.user = action.payload;
state.userFetchStatus = FetchStatus.success;
},
setUserFetchingStatus: (state, action: PayloadAction<FetchStatus>) => {
state.userFetchStatus = action.payload;
},
clearUserData: () => {
return initialUserState;
},
},
extraReducers: (builder) => {
builder.addDefaultCase((state) => {
return state;
});
},
});
export const { setUserData, clearUserData } = userSlice.actions;
export const getUserData = (state: RootStateType) => state.user;
export default userSlice.reducer;
我有一些组件可以触发 loginUser
然后尝试从 redux
控制台记录它
component.ts
const dispatch = useAppDispatch()
const user = useAppSelector(getUserData);
console.log(user)
<TouchableOpacity onPress={() => dispatch(loginUser)}>
//...
package.json
"react-redux": "^8.0.1",
"redux": "^4.2.0",
"redux-observable": "^2.0.0"
看起来 redux 存储没有改变,loginUser
动作正在触发但看起来 ofType(LOGIN_USER)
没有捕捉到它,我在其他一些线程和文档中看到使用 filter(actionFunction.match),
而不是 ofType
,但我认为这仅适用于 redux 操作?当我使用过滤器时,我收到一个已弃用的错误。
您必须致电您的动作创建者:
dispatch(loginUser())
,不是dispatch(loginUser)
。
除此之外,您绝对不应该手动编写该动作创建器 - 如果您不想使用 createSlice
来创建它,至少使用 createAction
来实现它。
export const loginUser = createAction('user/login')
.
那你也可以用filter(loginUser.match)
搭配它
我尝试按照文档进行操作,这就是我所做的
middleware/index.ts
import { combineEpics } from "redux-observable";
import userEpic from "./userEpic";
export const rootEpic = combineEpics(
userEpic,
);
store.ts
import { configureStore } from "@reduxjs/toolkit";
import { createEpicMiddleware } from "redux-observable";
import { rootEpic } from "../middleware";
import userReducer from "./reducers/userSlice";
const rootReducer = {
user: userReducer,
};
const epicMiddleware = createEpicMiddleware();
export const store = configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(epicMiddleware),
});
epicMiddleware.run(rootEpic);
export type RootStateType = ReturnType<typeof store.getState>;
export type AppDispatchType = typeof store.dispatch;
export default store;
actions.ts
export const LOGIN_USER = "LOGIN_USER";
export const loginUser = () => {
return {
type: LOGIN_USER,
} as const;
};
export type LoginUserAction = ReturnType<typeof loginUser>;
userEpic.ts(这是 API 调用的位置,但我这样做只是为了测试它是否有效)
import { Action } from "@reduxjs/toolkit";
import { Observable } from "rxjs";
import { combineEpics, ofType } from "redux-observable";
import { LOGIN_USER } from "./actions";
import { map } from "rxjs/operators";
import { setUserData } from "../../redux/reducers/userSlice";
const fetchUserEpic = (action$: Observable<Action>) => {
return action$.pipe(
ofType(LOGIN_USER),
map(() =>
setUserData({
id: 12,
name: "test",
surname: "test",
username: "test",
refreshToken: "test",
accessToken: "test",
})
)
);
};
export default combineEpics(fetchUserEpic);
userSlice.ts
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { FetchStatus } from "../../modules/types";
import { RootStateType } from "../store";
type UserType = {
id: number;
name: string;
surname: string;
username: string;
refreshToken: string;
accessToken: string;
};
type UserStateType = {
user: UserType | null;
userFetchStatus: FetchStatus;
};
const initialUserState: UserStateType = {
user: null,
userFetchStatus: FetchStatus.success,
};
export const userSlice = createSlice({
name: "user",
initialState: initialUserState,
reducers: {
setUserData: (state, action: PayloadAction<UserType>) => {
state.user = action.payload;
state.userFetchStatus = FetchStatus.success;
},
setUserFetchingStatus: (state, action: PayloadAction<FetchStatus>) => {
state.userFetchStatus = action.payload;
},
clearUserData: () => {
return initialUserState;
},
},
extraReducers: (builder) => {
builder.addDefaultCase((state) => {
return state;
});
},
});
export const { setUserData, clearUserData } = userSlice.actions;
export const getUserData = (state: RootStateType) => state.user;
export default userSlice.reducer;
我有一些组件可以触发 loginUser
然后尝试从 redux
component.ts
const dispatch = useAppDispatch()
const user = useAppSelector(getUserData);
console.log(user)
<TouchableOpacity onPress={() => dispatch(loginUser)}>
//...
package.json
"react-redux": "^8.0.1",
"redux": "^4.2.0",
"redux-observable": "^2.0.0"
看起来 redux 存储没有改变,loginUser
动作正在触发但看起来 ofType(LOGIN_USER)
没有捕捉到它,我在其他一些线程和文档中看到使用 filter(actionFunction.match),
而不是 ofType
,但我认为这仅适用于 redux 操作?当我使用过滤器时,我收到一个已弃用的错误。
您必须致电您的动作创建者:
dispatch(loginUser())
,不是dispatch(loginUser)
。
除此之外,您绝对不应该手动编写该动作创建器 - 如果您不想使用 createSlice
来创建它,至少使用 createAction
来实现它。
export const loginUser = createAction('user/login')
.
那你也可以用filter(loginUser.match)
搭配它