我正在将 Redux Toolkit 用于 Expo 应用程序。在这个应用程序中,我有一个 user.js,它是一个 redux 工具包切片。该切片包含身份验证信息(用户数据、访问 token 、刷新 token )。问题是服务器上的 session 会在 15 分钟后过期。
我的客户要求在 15 分钟后从应用程序中注销用户。
我的问题是:如何在 redux 工具包切片中实现此目的?一种方法可以是向我的状态添加一个logging_at时间戳,并且对于每个API请求,检查耗时(比较logged_at>现在),但我想让它以正确的方式进行,我觉得这种方法不是很 Eloquent 或可用。
如何使用 redux/redux 工具包在 X 时间过去后调度一个操作来注销用户?
最佳答案
简单方法:选择器
存储时间戳对我来说听起来不错。我可能更喜欢存储过期时间戳 expiresAt
而不是 loggedAt
。
您可以在选择器函数中添加一些逻辑,从而无需显式“注销”操作。我们可以将过期的用户保留在状态中,但在访问之前对其进行验证。该函数仅在用户对象仍然有效时返回该用户对象,如果该对象已过期则返回 null。
const selectUser = (state) => Date.now() > state.user.expiresAt ? null : state.user.user;
预定发货
您可以使用 setTimeout
安排调度
,但您必须在应用的最高级别执行此操作,而不是在调度的组件中进行
登录。我创建了a little demo 10 秒后自动注销。 useEffect
Hook 检测状态中 isLoggedIn
属性的更改(可以通过选择器派生),并在 isLoggedIn
变为 时安排注销正确
。
const App = () => {
const isLoggedIn = useSelector((state) => state.user.isLoggedIn);
const dispatch = useDispatch();
useEffect(
() => {
if (isLoggedIn) {
setTimeout(
() => {
dispatch(logOut());
alert("Logged Out");
},
// log out after 10 seconds
10 * 1000
);
}
},
// respond to changes in isLoggedIn
[dispatch, isLoggedIn]
);
return <LogIn />;
};
Redux-Saga
您可以使用 redux-saga 安排注销以响应登录。您想要创建一个非阻塞 fork
与 delay
15分钟。通过 saga,您还可以 cancel
如果用户在时间到之前自行注销,则任务。
它类似于 this example用于重试使用 2000 毫秒延迟的 API 调用。
异步重击
我们可以使用createAsyncThunk
来安排调度
有很长的延迟。在解决此问题之前,用户可能已经注销,并且可能有其他用户登录。您可以通过在reducer 或thunk 中检查用户名与当前用户名来处理此问题。
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
interface User {
username: string;
}
type UserState = User | null;
const initialState = null as UserState;
const wait = (ms: number) =>
new Promise<void>((resolve) => {
setTimeout(() => resolve(), ms);
});
export const asyncLogIn = createAsyncThunk(
"user/asyncLogIn",
async (user: User) => {
await wait(10 * 1000);
return user;
}
);
const userSlice = createSlice({
name: "user",
initialState,
reducers: {
// manual log out
logOut() {
return null;
}
},
extraReducers: (builder) =>
builder
// log in when thunk is initiated
.addCase(asyncLogIn.pending, (state, action) => {
const user = action.meta.arg;
return user;
})
// log out when thunk finally resolves
.addCase(asyncLogIn.fulfilled, (state, action) => {
// only log out if this user is still the logged in user
if (action.payload.username === state?.username) {
return null;
}
})
});
export const { logOut } = userSlice.actions;
export default userSlice.reducer;
关于reactjs - Expo、Redux Toolkit、为用户切片数据( session )设置超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67023927/