在我的 redux 调度 logout
操作后,我想重置为初始状态。我正在使用 nextjs
,但我不明白为什么 authenticateSlice.js
中我想要的注销缩减程序没有执行。我还使用了 redux-persist
来保持我的状态持久。
这是我来自 store.js 的代码
import { configureStore } from "@reduxjs/toolkit";
import authenticateSlice from "./slices/authenticateSlice";
import { persistReducer, persistStore } from "redux-persist"; // import persistStore
import storage from "./storage";
import { encryptTransform } from "redux-persist-transform-encrypt";
import { combineReducers } from "redux";
import thunk from "redux-thunk";
const reducers = combineReducers({
auth: authenticateSlice.reducer,
});
let transforms = null;
if (process.env.NODE_ENV === "production") {
const encrypt = encryptTransform({
secretKey: process.env.NEXT_PUBLIC_REDUX_SECRET,
onError: function (error) {
// Handle the error.
},
});
transforms = [encrypt];
}
const persistConfig = {
key: "root",
storage: storage,
transforms,
};
const persistedReducer = persistReducer(persistConfig, reducers);
const store = configureStore({
reducer: persistedReducer,
middleware: [thunk],
});
let persistor = persistStore(store); // initialize persistor
export { store, persistor };
这是我来自 authenticateSlice.js
的代码,我有 logout
函数来调度。
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import { commonPostRequest } from "@/django-api/common/commonRequestAPI";
import { CommonPostHeader } from "@/django-api/common/commonHeadersAPI";
export const fetchUserLogin = createAsyncThunk(
"auth/login",
async (arg, { rejectWithValue }) => {
const { username, password } = arg;
try {
const loginRequest = await commonPostRequest({
body: { username: username, password: password },
headers: CommonPostHeader,
url: "http://localhost:8000/api/accounts_app/login",
});
if (loginRequest.data) {
return loginRequest.data;
} else {
throw new Error(loginRequest.message);
}
} catch (err) {
return rejectWithValue(err.message);
}
}
);
export const logout = () => {
return { type: "auth/logout" };
};
// loading: 'idle' | 'pending' | 'succeeded' | 'failed'
const initialState = {
data: {},
loading: "idle",
message: "",
};
const authenticateSlice = createSlice({
name: "auth",
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchUserLogin.pending, (state) => {
state.loading = "pending";
})
.addCase(fetchUserLogin.fulfilled, (state, action) => {
state.loading = "succeeded";
state.data = action.payload;
})
.addCase(fetchUserLogin.rejected, (state, action) => {
state.loading = "failed";
state.message = action.payload;
})
.addCase(logout, (state) => {
Object.assign(state, initialState);
});
},
});
export default authenticateSlice;
最后,这是我的 Header
函数组件,我想在其中分派(dispatch)切片中的 logout
操作或分派(dispatch)注销函数以返回初始状态。
import { Typography } from "@mui/material";
import { Row, Col, Divider, notification } from "antd";
import styles from "./Header.module.scss";
import Image from "next/image";
import Link from "next/link";
import {
toLocalZoneDateTime,
getCurrentDateTimeStamp,
} from "../common/functions/datetime";
import { useDispatch } from "react-redux";
import { useRouter } from "next/router";
import { logout } from "../../next-redux/slices/authenticateSlice";
const Header = (props) => {
const dispatch = useDispatch();
const { user } = props;
const router = useRouter();
const currentDateTimeStamp = getCurrentDateTimeStamp();
const handleLogoutClick = (e) => {
e.preventDefault();
console.log("logout");
dispatch(logout());
};
return (
<>
<Row>
<Col span={24}>
<Row gutter={[8, 8]} className={styles.topBar}>
<Col span={12}>
<Typography variant="subtitle2" className={styles.topDate}>
{toLocalZoneDateTime(currentDateTimeStamp)}
</Typography>
</Col>
<Col span={12}>
{user ? (
<Typography align="right">
<a
onClick={(e) => {
handleLogoutClick(e);
}}
className={styles.topBarLinks}
>
Logout
</a>
</Typography>
) : (
<>
<Typography align="right">
{" "}
<Link href="/signin/" className={styles.topBarLinks}>
Sign-in
</Link>{" "}
<Link href="/signup/" className={styles.topBarLinks}>
Sign-up
</Link>
</Typography>
</>
)}
</Col>
</Row>
</Col>
</Row>
</>
);
};
export default Header;
最佳答案
问题
logout
是一个函数,而不是一个操作对象,因此额外的 reducer 案例没有运行。
export const logout = () => {
return { type: "auth/logout" };
};
...
.addCase(logout, (state) => { // <-- function, e.g. logout.type undefined
Object.assign(state, initialState);
});
解决方案
解决方案是通过 createAction
将 logout
声明为创建的操作实用程序。
import { createSlice, createAction, createAsyncThunk } from "@reduxjs/toolkit";
import { commonPostRequest } from "@/django-api/common/commonRequestAPI";
import { CommonPostHeader } from "@/django-api/common/commonHeadersAPI";
export const fetchUserLogin = createAsyncThunk(
...
);
export const logout = createAction("auth/logout");
const initialState = { ... };
const authenticateSlice = createSlice({
name: "auth",
initialState,
extraReducers: (builder) => {
builder
.addCase(fetchUserLogin.pending, (state) => {
state.loading = "pending";
})
.addCase(fetchUserLogin.fulfilled, (state, action) => {
state.loading = "succeeded";
state.data = action.payload;
})
.addCase(fetchUserLogin.rejected, (state, action) => {
state.loading = "failed";
state.message = action.payload;
})
.addCase(logout, (state) => {
return initialState;
});
},
});
export default authenticateSlice.reducer;
或者声明一个logout
reducer 案例,它将生成可以导出的logout
操作。
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import { commonPostRequest } from "@/django-api/common/commonRequestAPI";
import { CommonPostHeader } from "@/django-api/common/commonHeadersAPI";
export const fetchUserLogin = createAsyncThunk(
...
);
const initialState = { ... };
const authenticateSlice = createSlice({
name: "auth",
initialState,
reducers: {
logout: (state) => {
return initialState;
},
},
extraReducers: (builder) => {
builder
.addCase(fetchUserLogin.pending, (state) => {
state.loading = "pending";
})
.addCase(fetchUserLogin.fulfilled, (state, action) => {
state.loading = "succeeded";
state.data = action.payload;
})
.addCase(fetchUserLogin.rejected, (state, action) => {
state.loading = "failed";
state.message = action.payload;
});
},
});
export const { logout } = authenticateSlice.actions;
export default authenticateSlice.reducer;
关于javascript - 注销时 Redux 不会返回到我的初始状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75915762/