
RTK: 全域狀態
一個app 只會有一個 snackbar 非常適合RTK全域管理,任何component、page 都可以直接呼叫
tsx
1// src/store/slices/snackbarSlice.ts
2import { createSlice } from "@reduxjs/toolkit";
3import { AlertColor } from "@mui/material";
4// const defaultDuration = 3000;
5const snackbarSlice = createSlice({
6 name: "snackbar",
7 initialState: {
8 open: false,
9 message: "",
10 severity: "success" as AlertColor,
11 autoHideDuration: 3000,
12 },
13 reducers: {
14 showSnackbar: (state, action) => {
15 state.open = true;
16 state.message = action.payload.message;
17 state.severity = action.payload.severity;
18 state.autoHideDuration =
19 action.payload.autoHideDuration === undefined
20 ? 3000
21 : action.payload.autoHideDuration;
22 },
23 closeSnackbar: (state) => {
24 state.open = false;
25 },
26 },
27});
28
29export const { showSnackbar, closeSnackbar } = snackbarSlice.actions;
30export default snackbarSlice.reducer;
31Zustand: 單頁 page state
像是某個頁面的 Drawer 是否開啟,但unmount 的時候要 cleanup 不要佔記憶體
tsx
1// src/app/some page/_store/useMobileFilterDrawerStore.ts
2import { create } from "zustand";
3
4interface MobileFilterDrawerState {
5 isMobileFilterDrawerOpen: boolean;
6 open: () => void;
7 close: () => void;
8 toggle: () => void;
9}
10
11export const useMobileFilterDrawerStore = create<MobileFilterDrawerState>(
12 (set) => ({
13 isMobileFilterDrawerOpen: false,
14 open: () => set({ isMobileFilterDrawerOpen: true }),
15 close: () => set({ isMobileFilterDrawerOpen: false }),
16 reset: () => set({ isMobileFilterDrawerOpen: false }), // <-- 清空回初始狀態
17 })
18);tsx
1// src/app/some page
2import { useEffect } from "react";
3import { useMobileFilterDrawerStore } from "@/app/somepage/_store/useMobileFilterDrawerStore";
4
5export default function SomeComponent() {
6 const { isMobileFilterDrawerOpen, open, close, reset } =
7 useMobileFilterDrawerStore();
8
9 // Component unmount 時 cleanup
10 useEffect(() => {
11 return () => {
12 reset(); // <-- 在離開頁面或元件unmount時清空
13 };
14 }, [reset]);
15
16 return (
17 <>
18 <button onClick={open}>Open Drawer</button>
19 <button onClick={close}>Close Drawer</button>
20 {isMobileFilterDrawerOpen && <div>Drawer Content</div>}
21 </>
22 );
23}
24