首页 > 解决方案 > Redux saga 函数在第一次尝试时没有运行

问题描述

所以,每当我启动我的服务器时。我不知道为什么,但我的 saga 功能在登录时不起作用。我已确保该操作正在运行。此外,一旦我重新加载页面,它就会开始工作。

这是我设置观察者的方式。

export function* watchUserLogin() {
  console.log("login");
  yield takeEvery(LOGIN_USER, loginUser);
}

export function* watchUserLogout() {
  yield takeEvery(LOGOUT_USER, logoutUser);
}

function* authSaga() {
  yield all([fork(watchUserLogin), fork(watchUserLogout)]);
} 

也是我的主要传奇功能

function* loginUser({ payload: { user, history } }) {
  try {
    console.log("login");
    const response = yield call(Login, user.email, user.password);
    console.log(response, "ah");
    if (response.status >= 200 && response.status < 300) {
      const user = yield response.data;

      sessionStorage.setItem("authUser", JSON.stringify(user));
      console.log(user);
      var decoded = jwt_decode(user.access);
      yield put(loginSuccess(user));
      if (decoded.is_preferences) {
        history.push("/dashboard");
        // const session = yield call(checkSession);
        // console.log(session);
        console.log(sessionStorage.getItem("authUser"));
      } else {
        history.push("/preferences");
        // const session = yield call(checkSession);
        // console.log(session);
      }
    } else {
      throw response;
    }
    yield put(loginSuccess(user));
  } catch (error) {
    console.log(error.response.status);
    yield put(loginFail(error.response.data, error.response.status));
  }
}

标签: reactjsreduxreact-reduxredux-saga

解决方案


我正在使用takeLatest()来自 Redux-saga 的效果来回答这个问题(其他 saga 方法也很好,您应该查看 saga 效果以找出与您的用例匹配的效果)您可以在您的 saga 方法下添加它:

export function* loginUser({ payload: { user, history } }) {
...
}

export const authSaga = [
 takeLatest(LOGIN_USER, loginUser),
 takeLatest(LOGOUT_USER, logoutUser)
]

在你的 rootSaga 中导入这个 saga,或者如果你缺少这个,就创建一个:

export function* rootSaga() {
    yield all([
        ...authSaga
    ]);
}

在您配置 redux 存储并应用中间件的位置添加此 rootSaga:

import { createStore, applyMiddleware } from "redux";
import { reducers } from "../core/state";
import { createBrowserHistory } from "history";
import createSagaMiddleware from "redux-saga";
import { routerMiddleware } from "connected-react-router";
import { logger } from 'redux-logger';
import thunk from 'redux-thunk';
import { rootSaga } from "../core/state/rootSaga";
import { composeWithDevTools } from 'redux-devtools-extension';

export const history = createBrowserHistory();

const configureStore = (initialState = {}) => {
  const sagaMiddleware = createSagaMiddleware();
  let middleware = [sagaMiddleware, routerMiddleware(history), thunk]
  const store = createStore(
    reducers(history),
    initialState,
    composeWithDevTools(
      applyMiddleware(...middleware),
    )
  );
  sagaMiddleware.run(rootSaga);
  return store;
};

export default () => configureStore({});

并非所有上述代码都需要添加,这只是我的一个项目的 configStore 示例,对于您的情况,请务必在您的配置中添加以下行:

sagaMiddleware.run(rootSaga);

做什么takeLatest()?:

在发送到与模式匹配的 Store 的每个操作上产生一个 saga。如果它仍在运行,则自动取消之前启动的任何以前的 saga 任务。

每次将操作分派到商店时。如果此操作与模式匹配,则 takeLatest 在后台启动一个新的 saga 任务。如果之前启动了一个 saga 任务(在实际操作之前调度的最后一个操作上),并且如果该任务仍在运行,则该任务将被取消。


推荐阅读