使用 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)搭配它