Skip to content

Commit a523daa

Browse files
Rewrite the library to support multiple cases
1 parent 5c5f543 commit a523daa

22 files changed

+1119
-885
lines changed

README.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,34 +133,35 @@ export const store = configurePersistedStore(
133133
// counter: counterReducer,
134134
},
135135
},
136+
'applicationId',
136137
storage
137138
);
138139

139-
export type RootState = ReturnType<typeof store.getState>;
140-
export type AppDispatch = typeof store.dispatch;
140+
type Store = Awaited<typeof store>;
141+
export type RootState = ReturnType<Store['getState']>;
142+
export type AppDispatch = Store['dispatch'];
141143
```
142144

143145

144146
## 🛠️ API
145147

146-
### `createPersistedSlice(sliceOptions, [filterFunction])`
148+
### `createPersistedSlice(sliceOptions)`
147149

148150
A wrapper around RTK's `createSlice`.
149151
* **`sliceOptions`**: The standard `CreateSliceOptions` object.
150-
* **`filterFunction`** (optional): A function `(state) => partialState` to select which parts of the state to persist.
151152

152-
### `createPersistedReducer(name, initialState, builderCallback, [filterFunction])`
153+
### `createPersistedReducer(name, initialState, builderCallback)`
153154

154155
A wrapper around RTK's `createReducer`.
155156
* **`name`**: A unique string to identify this reducer in storage.
156157
* **`initialState`**: The initial state for the reducer.
157158
* **`builderCallback`**: A callback that receives a `builder` object to define case reducers.
158-
* **`filterFunction`** (optional): A function `(state) => partialState` to select which parts of the state to persist.
159159

160-
### `configurePersistedStore(storeOptions, storageHandler)`
160+
### `configurePersistedStore(storeOptions, applicationId, storageHandler)`
161161

162162
A wrapper around RTK's `configureStore`.
163163
* **`storeOptions`**: The standard `ConfigureStoreOptions` object.
164+
* **`applicationId`**: A unique string that identifies the application.
164165
* **`storageHandler`**: A storage object that implements `getItem`, `setItem`, and `removeItem`.
165166

166167

example/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"react": "^19.1.0",
1515
"react-dom": "^19.1.0",
1616
"react-redux": "^9.2.0",
17-
"rtk-persist": "../rtk-persist-2.0.0-beta01.tgz"
17+
"rtk-persist": "./.."
1818
},
1919
"devDependencies": {
2020
"@eslint/js": "^9.30.1",

example/src/App.css

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,34 @@
1010

1111
.card {
1212
display: flex;
13-
flex-direction: row;
13+
flex-direction: column;
1414
align-items: center;
1515
justify-content: center;
1616
padding: 2em;
17-
gap: 2rem;
17+
gap: 1rem;
18+
border-radius: 12px;
19+
margin-bottom: 2rem;
20+
background-color: #efefef;
21+
}
22+
23+
.button-group {
24+
display: flex;
25+
gap: 1rem;
26+
}
27+
28+
.status-bar {
29+
border-radius: 8px;
30+
padding: 0.5rem 1.5rem;
31+
margin-bottom: 2rem;
32+
background-color: #efefef;
33+
color: #222222;
34+
}
35+
36+
.status-bar p {
37+
margin: 0.5rem 0;
38+
}
39+
40+
.status-bar strong {
41+
color: #222222;
42+
font-weight: 600;
1843
}

example/src/App.tsx

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,66 @@
1-
import './App.css'
2-
import { decrement, increment } from './state/counter/reducer'
3-
import { useAppDispatch, useAppSelector } from './state/hooks'
1+
import './App.css';
2+
import { counterSlice } from './state/counter/slice';
3+
import { useAppDispatch, useAppSelector } from './state/hooks';
4+
import { setPaused } from './state/status/slice';
5+
import { store as storePromise } from './state/store';
46

57

68
function App() {
7-
// The `state` arg is correctly typed as `RootState` already
8-
const count = useAppSelector((state) => state.counter.value)
9-
const dispatch = useAppDispatch()
9+
const count = useAppSelector((state) => state.counter.value);
10+
const { isPaused } = useAppSelector((state) => state.status);
11+
const dispatch = useAppDispatch();
12+
13+
const handlePause = async () => {
14+
const store = await storePromise;
15+
store.pausePersist();
16+
dispatch(setPaused(true));
17+
};
18+
19+
const handleResume = async () => {
20+
const store = await storePromise;
21+
store.resumePersist();
22+
dispatch(setPaused(false));
23+
};
24+
25+
const handleClear = async () => {
26+
const store = await storePromise;
27+
await store.clearPersistedState();
28+
// Reload to show the state has been reset from storage.
29+
window.location.reload();
30+
};
1031

1132
return (
1233
<>
13-
<h1>count is {count}</h1>
34+
<h1>rtk-persist Example</h1>
35+
<div className="status-bar">
36+
<p>Persistence Status: <strong>{isPaused ? 'Paused' : 'Active'}</strong></p>
37+
</div>
38+
39+
<div className="card">
40+
<h2>Counter Value: {count}</h2>
41+
<div className='button-group'>
42+
<button onClick={() => dispatch(counterSlice.actions.decrement())}>
43+
-
44+
</button>
45+
<button onClick={() => dispatch(counterSlice.actions.increment())}>
46+
+
47+
</button>
48+
</div>
49+
</div>
50+
1451
<div className="card">
15-
{/* <button onClick={() => dispatch(counterSlice.actions.decrement())}>
16-
-
17-
</button>
18-
<button onClick={() => dispatch(counterSlice.actions.increment())}>
19-
+
20-
</button> */}
21-
<button onClick={() => dispatch(decrement(1))}>
22-
-
23-
</button>
24-
<button onClick={() => dispatch(increment(1))}>
25-
+
26-
</button>
52+
<h2>Persistence Controls</h2>
53+
<div className='button-group'>
54+
<button onClick={handlePause} disabled={isPaused}>
55+
Pause
56+
</button>
57+
<button onClick={handleResume} disabled={!isPaused}>
58+
Resume
59+
</button>
60+
<button onClick={handleClear} style={{ backgroundColor: '#c0392b' }}>
61+
Clear and Reload
62+
</button>
63+
</div>
2764
</div>
2865
</>
2966
)

example/src/main.tsx

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,26 @@ import { createRoot } from 'react-dom/client'
33
import { Provider } from 'react-redux'
44
import App from './App.tsx'
55
import './index.css'
6-
import { store } from './state/store.ts'
7-
8-
createRoot(document.getElementById('root')!).render(
9-
<StrictMode>
10-
<Provider store={store}>
11-
<App />
12-
</Provider>
13-
</StrictMode>,
14-
)
6+
import { store as storePromise } from './state/store.ts'
7+
8+
// Get the root element from the DOM.
9+
const rootElement = document.getElementById('root')!;
10+
const root = createRoot(rootElement);
11+
12+
// Create an async function to initialize and render the app.
13+
const startApp = async () => {
14+
// Await the store promise to ensure the store is created and rehydrated.
15+
const store = await storePromise;
16+
17+
// Once the store is ready, render the application.
18+
root.render(
19+
<StrictMode>
20+
<Provider store={store}>
21+
<App />
22+
</Provider>
23+
</StrictMode>
24+
);
25+
};
26+
27+
// Call the async function to start the application.
28+
startApp();

example/src/state/counter/reducer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export const increment = createAction<number>('increment');
55
export const decrement = createAction<number>('decrement');
66

77
export const reducer = createPersistedReducer(
8-
'counter', // A unique name for the reducer
8+
'counterR', // A unique name for the reducer
99
{ value: 0 }, // Initial state
1010
(builder) => {
1111
builder

example/src/state/status/slice.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
2+
3+
interface StatusState {
4+
isPaused: boolean;
5+
}
6+
7+
const initialState: StatusState = {
8+
isPaused: false,
9+
};
10+
11+
export const statusSlice = createSlice({
12+
name: 'status',
13+
initialState,
14+
reducers: {
15+
setPaused: (state, action: PayloadAction<boolean>) => {
16+
state.isPaused = action.payload;
17+
},
18+
},
19+
});
20+
21+
export const { setPaused } = statusSlice.actions;
22+
23+
export default statusSlice.reducer;

example/src/state/store.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
import { configurePersistedStore } from 'rtk-persist'
2-
// import { counterSlice } from './counter/slice'
3-
import { reducer } from './counter/reducer'
4-
1+
import { configurePersistedStore } from 'rtk-persist';
2+
import { counterSlice } from './counter/slice';
3+
import { statusSlice } from './status/slice';
54

65
export const store = configurePersistedStore({
76
reducer: {
8-
// [counterSlice.name]: counterSlice.reducer,
9-
'counter': reducer,
7+
[counterSlice.name]: counterSlice.reducer,
8+
// You can swap the slice with the reducer to test both implementations
9+
// counter: counterReducer,
10+
[statusSlice.name]: statusSlice.reducer,
1011
},
11-
}, localStorage)
12+
}, 'countersApp', localStorage);
1213

13-
export type RootState = ReturnType<typeof store.getState>
14-
export type AppDispatch = typeof store.dispatch
14+
export type Store = Awaited<typeof store>;
15+
export type RootState = ReturnType<Store['getState']>;
16+
export type AppDispatch = Store['dispatch'];

example/vite.config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { defineConfig } from 'vite'
21
import react from '@vitejs/plugin-react'
2+
import { defineConfig } from 'vite'
33

44
// https://vite.dev/config/
55
export default defineConfig({
6-
plugins: [react()],
6+
plugins: [react()]
77
})

0 commit comments

Comments
 (0)