react redux传奇没有付诸行动



我正在尝试实现以下内容-用户可以登录,但在5秒钟后,他们将自动注销。我与JSONWEBTOKEN tho合作。

这是我尝试使用redux sagas与react:

app.ts文件(存储的根目录(:

import { applyMiddleware, combineReducers, compose, createStore, Reducer } from 'redux';
import createSagaMiddleware from 'redux-saga';
import * as fromAuth from './reducers/auth';
import { watchAuth } from './sagas/auth';
export interface AppState {
auth: fromAuth.State;
}
const composeEnhancers: typeof compose = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const sagaMiddleware = createSagaMiddleware();
const rootReducer: Reducer<AppState> = combineReducers({
auth: fromAuth.reducer,
});
export const store = createStore(rootReducer, composeEnhancers(applyMiddleware(sagaMiddleware)));
sagaMiddleware.run(watchAuth);

传奇文件:

import { ForkEffect, put, select, takeEvery } from 'redux-saga/effects';
import * as fromApp from '../app';
import * as authActions from '../actions/auth';
// --- Workers (Effects) --- //
function* loginSaga() {
const logoutTimeoutCreationDate: string | null = yield localStorage.getItem('logoutTimeoutCreationDate');
let logoutTimeout: number;
if (
!logoutTimeoutCreationDate ||
new Date(logoutTimeoutCreationDate).getTime() + 5000 < new Date().getTime()
) {
yield localStorage.setItem('logoutTimeoutCreationDate', new Date().toISOString());
logoutTimeout = yield 5000;
} else {
logoutTimeout = yield new Date(logoutTimeoutCreationDate).getTime() + 5000 - new Date().getTime();
}
const newTimeout: NodeJS.Timeout = yield setTimeout(() => put(authActions.logout()), logoutTimeout);
yield put(authActions.setLogoutTimeout(newTimeout));
}
function* logoutSaga() {
const timeout: NodeJS.Timeout = yield select((state: fromApp.AppState) => state.auth.logoutTimeout);
yield clearTimeout(timeout);
yield sessionStorage.removeItem('token');
yield localStorage.removeItem('logoutTimeoutCreationDate');
yield put(authActions.setLogoutTimeout(null));
}
// --- Watchers --- //
export function* watchAuth():IterableIterator<ForkEffect>{
yield takeEvery(authActions.AUTH_LOGIN, loginSaga);
yield takeEvery(authActions.AUTH_LOGOUT, logoutSaga);
}

还原器文件:

import * as actions from '../actions/auth';
import { IUser } from '../../models/user';
export interface State {
user: IUser | null;
logoutTimeout: NodeJS.Timeout | null;
}
const initialState: State = {
user: null,
logoutTimeout: null,
};
export const reducer = (state: State = initialState, action: actions.AuthTypes): State => {
switch (action.type) {
case actions.AUTH_LOGOUT:
return { ...state, user: null };
case actions.AUTH_LOGIN:
return { ...state, user: action.payload.user };
case actions.AUTH_SET_LOGOUT_TIMEOUT:
return { ...state, logoutTimeout: action.payload.timeout };
default:
return state;
}
};

动作文件:

import { IUser } from '../../models/user';
export const AUTH_LOGOUT = '[Auth] Logout';
export const AUTH_LOGIN = '[Auth] Login';
export const AUTH_SET_LOGOUT_TIMEOUT = '[Auth] Set logout timeout';
// --- Interface --- //
export interface Logout {
type: typeof AUTH_LOGOUT;
}
export interface Login {
type: typeof AUTH_LOGIN;
payload: { user: IUser };
}
export interface SetLogoutTimeout {
type: typeof AUTH_SET_LOGOUT_TIMEOUT;
payload: { timeout: NodeJS.Timeout | null };
}
// --- Action creators --- //
export const logout = (): Logout => {
return {
type: AUTH_LOGOUT,
};
};
export const login = (user: IUser): Login => {
return {
type: AUTH_LOGIN,
payload: { user },
};
};
export const setLogoutTimeout = (timeout: NodeJS.Timeout | null): SetLogoutTimeout => {
return {
type: AUTH_SET_LOGOUT_TIMEOUT,
payload: { timeout },
};
};
export type AuthTypes = Logout | Login | SetLogoutTimeout;

我相信IUser代码与这个问题无关,所以我省略了它

问题是,一旦我登录,loginSaga函数内的行(在sagas文件中(,const newTimeout: NodeJS.Timeout = yield setTimeout(() => put(authActions.logout()), logoutTimeout);这是有效的,但put(authActions.logout())没有发生任何变化。就像我写的一样。

我也使用redux devtools,5秒后没有发出任何动作。为什么?

我对这里的环境感到困惑,或者你可能感到困惑?您使用的是DOM/窗口函数,但TypeScript类型声明为NodeJS.Timeout。该类型是一个对象,但在浏览器中调用setTimeout会返回一个数字。

看起来您正在将超时存储在localStorage和您的状态中。我认为这两个都没有必要,因为saga有一个内置的delay效果来处理这项任务。

这就是你所需要的:

import { ForkEffect, put, takeEvery, delay } from "redux-saga/effects";
import * as authActions from "./actions";
function* loginSaga() {
yield delay(5000);
yield put(authActions.logout());
}
export function* watchAuth(): IterableIterator<ForkEffect> {
yield takeEvery(authActions.AUTH_LOGIN, loginSaga);
}

CodeSandbox链接

最新更新