两天来我一直没有找到解决这个问题的办法。我的应用程序可以处理用户登录时的身份验证,但当一个用户注销和另一个用户登录在同一台计算机上时,重新获取数据的请求不会发送到后端,用户将使用前一个用户的数据登录。我真的不知道为什么会这样,但我在注销时清除了redux状态。我已经阅读了许多资源,但我似乎没有找到解决方案。
我尝试了一些建议性的解决方案,可以清除缓存,因为一些来源提到了缓存数据没有被清除。我已经做了很多jagons来解决这个问题,但不幸的是没有任何工作。我现在只是堆栈。
这是我的apiSlice.js代码
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
const BASE_URL = "http://localhost:10000/api/v1"
const baseQuery = fetchBaseQuery({
baseUrl: `${BASE_URL}/user`,
credentials: 'include',
prepareHeaders: (headers, { getState }) => {
const token = getState().user.token
console.log(token)
if (token) {
headers.set("Authorization", `Bearer ${token}`)
}
return headers
}
})
const baseQueryWithReauth = async (args, api, extraOptions) => {
let result = await baseQuery(args, api, extraOptions);
console.log(result)
if (result?.error?.originalStatus === 403) {
//send refresh token to get new access token
const refreshResult = await baseQuery('/token', api, extraOptions);
console.log(refreshResult)
if (refreshResult?.data) {
api.dispatch(setCredentials({ ...refreshResult.data }));
result = await baseQuery(args, api, extraOptions);
} else {
api.dispatch(logOut());
}
}
return result;
}
export const apiSlice = createApi({
reducerPath: 'authSlice',
baseQuery: baseQueryWithReauth,
tagTypes: ['User'],
endpoints: builder => ({}),
keepUnusedDataFor: 0,
})
这是authApi.js的代码
import { apiSlice } from "./apiSlice";
import { userApi } from "./userApi";
export const authApi = apiSlice.injectEndpoints({
endpoints: (builder) => ({
registerUser: builder.mutation({
query: (user) => ({
url: `/signup`,
method: "POST",
body: user
})
}),
loginUser: builder.mutation({
query: (data) => ({
url: '/login',
method: 'POST',
body: data,
credentials: 'include'
}),
providesTags: ['User']
}),
logoutUser: builder.mutation({
query: () => ({
url: "/logout",
method: 'POST',
credentials: "include"
}),
async onQueryStarted(args, { dispatch, queryFulfilled }) {
try {
await queryFulfilled
} catch (error) {
}
}
})
})
})
export const {
useRegisterUserMutation,
useLoginUserMutation,
useLogoutUserMutation
} = authApi;
这是我的userApi.js
import { apiSlice } from "./apiSlice";
export const userApi = apiSlice.injectEndpoints({
endpoints: (builder) => ({
getMe: builder.query({
query: () => ({
url: `/me?_=${new Date().getTime()}`,
credentials: "include",
}),
transformResponse: (result) => result.data.user,
async onQueryStarted(arg, { dispatch, queryFulfilled }) {
try {
const { data } = await queryFulfilled;
dispatch(setUser(data));
} catch (error) { }
},
}),
}),
})
export const { useGetMeQuery } = userApi
这是我的userSlice.js
import { createSlice } from '@reduxjs/toolkit';
const initialState = {
user: null,
token: null
};
const userSlice = createSlice({
initialState,
name: 'userSlice',
reducers: {
setCredentials: (state, action) => {
const { accessToken, data } = action.payload
state.token = accessToken
state.user = data;
},
logout: () => initialState,
setUser: (state, action) => {
state.user = action.payload;
},
},
});
export default userSlice;
export const userActions = userSlice.actions;
这是我的store.js
import { combineReducers, configureStore } from "@reduxjs/toolkit";
import { setupListeners } from "@reduxjs/toolkit/dist/query";
import myListSlice from "./features/myListSlice";
import { persistReducer, FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER } from "redux-persist";
import storage from "redux-persist/lib/storage";
import userSlice from "./features/userSlice";
import { apiSlice } from "./api/apiSlice";
const persistConfig = {
key: "root",
storage: storage
}
const rootReducer = combineReducers({
myList: myListSlice.reducer,
user: userSlice.reducer,
[apiSlice.reducerPath]: apiSlice.reducer,
})
const persistedReducer = persistReducer(persistConfig, rootReducer)
export const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({ serializableCheck: { ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER], } }).concat(apiSlice.middleware)
})
setupListeners(store.dispatch)
这是用于调度函数的Login.jsx代码
import React, { useEffect } from "react";
import { Link, useActionData, useNavigate, useSubmit } from "react-router-dom";
import Logo from "../../assets/images/Logo.svg";
import background from "../../assets/images/background.jpg";
import { useFormik } from "formik";
import { loginValidate } from "../../Validations/UserValidation";
import { useLoginUserMutation } from "../../Store/api/authApi";
import { useDispatch } from "react-redux";
import { userActions } from "../../Store/features/userSlice";
import Spinner from "../../Components/Spinner";
const Login = () => {
// const loading = false;
const [loginUser, { isLoading: loading }] = useLoginUserMutation();
const submit = useSubmit();
const navigate = useNavigate();
const data = useActionData();
const { setCredentials } = userActions;
const dispatch = useDispatch();
const formik = useFormik({
initialValues: {
email: "",
password: "",
},
validationSchema: loginValidate,
onSubmit: (values) => {
submit(values, { method: "post" });
},
});
useEffect(() => {
const fetchData = async () => {
if (data) {
try {
const { accessToken } = await loginUser(data).unwrap();
dispatch(setCredentials({ accessToken, data }));
navigate("/");
} catch (error) {
console.error(error);
}
}
};
fetchData();
}, [data]);
这是我的根.jsx
import { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Outlet, useNavigate } from "react-router-dom";
import Footer from "../Components/Footer";
import Navbar from "../Components/Navbar";
import Spinner from "../Components/Spinner";
import { useGetMeQuery } from "../Store/api/userApi";
import { userActions } from "../Store/features/userSlice";
function Root() {
const { token } = useSelector((state) => state.user);
const dispatch = useDispatch();
const { setUser } = userActions;
const { data: user, isLoading } = useGetMeQuery();
const navigate = useNavigate();
useEffect(() => {
if (token === null) {
navigate("/account");
}
dispatch(setUser(user));
}, []);
return (
<>
{isLoading ? (
<>
<Spinner />
</>
) : (
<div className="bg-black">
<Navbar user={user} />
<div className="flex flex-wrap items-center justify-between">
<Outlet />
</div>
<Footer />
</div>
)}
</>
);
}
export default Root;
1条答案
按热度按时间62o28rlo1#
当您使用useGetMeQuery访问用户数据时,数据将被缓存,并且在发出请求之前,将在后续请求中从缓存中获取数据,因此它将从该高速缓存中提供数据并终止请求,但是当您使用useLazyGetMeQuery时,它有助于在组件挂载时重新获取数据,并为其触发器(在这种情况下为getUser)提供调整false。它将在重新加载和组件安装时获取用户,但删除false将使缓存成为可能。