@t8/react-store 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +5 -3
  2. package/dist/index.js +30 -16
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -4,9 +4,9 @@
4
4
 
5
5
  [![npm](https://img.shields.io/npm/v/@t8/react-store?labelColor=345&color=46e)](https://www.npmjs.com/package/@t8/react-store) ![Lightweight](https://img.shields.io/bundlephobia/minzip/@t8/react-store?label=minzip&labelColor=345&color=46e) ![CSR ✓](https://img.shields.io/badge/CSR-✓-345?labelColor=345) ![SSR ✓](https://img.shields.io/badge/SSR-✓-345?labelColor=345)
6
6
 
7
- **Why?** To fill the gap with a state management lib that at the same time: (1) has a simple API introducing as few new entities as possible, (2) closely follows the React's `useState()` pattern of initializing and manipulating the state to fulfill the common task of migration from local state to shared state quickly without sizable rewrites, (3) doesn't internally make use of global stores or other global variables by default and works smoothly with SSR with regular React Contexts.
7
+ **Why?** To have an easy-to-use state management lib for React apps requiring least effort to migrate from local state and to quickly set up shared state from scratch, whether with SSR or without. Other approaches, including Redux Toolkit, Zustand, Jotai, MobX, invariably depart from this picture to varying degrees.
8
8
 
9
- **Features**: `useState()`-like API for shared state, quick transition from local state, no boilerplate, easily integrates with Immer, SSR- and CSR-compatible.
9
+ This picture is achieved here by (1) having a simple API introducing as few new entities as possible, (2) closely following the React's `useState()` pattern of initializing and manipulating the state to avoid boilerplate and sizable rewrites in the common task of migration from local state to shared state, (3) working smoothly with SSR with regular React Contexts without requiring a specifically designed setup and without internally making use of global stores or other global variables by default.
10
10
 
11
11
  <!-- docsgen-show-start --
12
12
  ```diff
@@ -183,4 +183,6 @@ import { PersistentStore } from "@t8/react-store";
183
183
  let counterStore = new PersistentStore(0, "counter");
184
184
  ```
185
185
 
186
- Whenever it's updated, `counterStore` above will save its state to the `"counter"` key of `localStorage`. (Pass `true` as the third parameter of `new PersistentStore()` to use `sessionStorage` instead of `localStorage`.) Also, the store's initial state value is restored from the browser storage. Otherwise, `counterStore` works pretty much like a regular store described above.
186
+ The store's state value is initially restored from and saved whenever updated to the `"counter"` key of `localStorage`. (Pass `{ session: true }` as the `options` parameter of `new PersistentStore(data, storageKey, options?)` to use `sessionStorage` instead of `localStorage`.) Otherwise, `counterStore` works pretty much like a regular store described above.
187
+
188
+ The way data gets saved to and restored from a browser storage entry (including filtering out certain data or otherwise rearranging the saved data) can be overridden by setting `options.serialize` and `options.deserialize` in `new PersistentStore(data, storageKey, options?)`. By default, they are `JSON.stringify()` and `JSON.parse()`.
package/dist/index.js CHANGED
@@ -35,32 +35,43 @@ var Store = class {
35
35
  };
36
36
 
37
37
  // node_modules/@t8/store/src/PersistentStore.ts
38
- function getStorage(session) {
38
+ function getStorage(session = false) {
39
39
  if (typeof window === "undefined") return;
40
40
  return session ? sessionStorage : localStorage;
41
41
  }
42
42
  var PersistentStore = class extends Store {
43
43
  storageKey;
44
- session;
44
+ options;
45
45
  synced = false;
46
46
  /**
47
47
  * Creates an instance of the container for data persistent across page
48
48
  * reloads.
49
49
  *
50
50
  * The store data is saved to and restored from the given `storageKey`
51
- * either of `localStorage` if the `session` parameter is `false` (which is
52
- * the default), or of `sessionStorage` if `session` is set to `true`.
53
- * Interaction with the browser storage is skipped in non-browser environments.
51
+ * either of `localStorage` (by default) or `sessionStorage` (if `options.session`
52
+ * is set to `true`). Interaction with the browser storage is skipped in
53
+ * non-browser environments.
54
54
  *
55
55
  * @example
56
56
  * ```js
57
57
  * let counterStore = new PersistentStore(0, "counter");
58
58
  * ```
59
+ *
60
+ * The way data gets saved to and restored from a browser storage entry
61
+ * (including filtering out certain data or otherwise rearranging the
62
+ * saved data) can be overridden by setting `options.serialize` and
63
+ * `options.deserialize`. By default, they are `JSON.stringify()` and
64
+ * `JSON.parse()`.
59
65
  */
60
- constructor(data, storageKey, session = false) {
66
+ constructor(data, storageKey, options) {
61
67
  super(data);
62
68
  this.storageKey = storageKey;
63
- this.session = session;
69
+ this.options = {
70
+ session: false,
71
+ serialize: (data2) => JSON.stringify(data2),
72
+ deserialize: (content) => JSON.parse(content),
73
+ ...options
74
+ };
64
75
  this.onUpdate(() => {
65
76
  if (this.synced) this.save();
66
77
  });
@@ -69,10 +80,11 @@ var PersistentStore = class extends Store {
69
80
  * Saves the store state value to the browser storage.
70
81
  */
71
82
  save() {
72
- let storage = getStorage(this.session);
73
- if (this.synced && storage) {
83
+ let storage = getStorage(this.options?.session);
84
+ let serialize = this.options?.serialize;
85
+ if (this.synced && storage && typeof serialize === "function") {
74
86
  try {
75
- storage.setItem(this.storageKey, JSON.stringify(this.state));
87
+ storage.setItem(this.storageKey, serialize(this.state));
76
88
  } catch {
77
89
  }
78
90
  }
@@ -81,18 +93,20 @@ var PersistentStore = class extends Store {
81
93
  * Signals the store to read the state value from the browser storage.
82
94
  */
83
95
  sync() {
84
- let storage = getStorage(this.session);
85
- let rawState = null;
86
- if (storage) {
96
+ let storage = getStorage(this.options?.session);
97
+ let deserialize = this.options?.deserialize;
98
+ let serializedState = null;
99
+ if (storage && typeof deserialize === "function") {
87
100
  try {
88
- rawState = storage.getItem(this.storageKey);
89
- if (rawState !== null) this.setState(JSON.parse(rawState));
101
+ serializedState = storage.getItem(this.storageKey);
102
+ if (serializedState !== null)
103
+ this.setState(deserialize(serializedState, this.state));
90
104
  } catch {
91
105
  }
92
106
  }
93
107
  if (!this.synced) {
94
108
  this.synced = true;
95
- if (rawState === null) this.save();
109
+ if (serializedState === null) this.save();
96
110
  }
97
111
  }
98
112
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@t8/react-store",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Small React app state management lib aligned with React's state pattern, condensed to the essentials",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -45,6 +45,6 @@
45
45
  "typescript": "^5.9.3"
46
46
  },
47
47
  "dependencies": {
48
- "@t8/store": "^1.3.2"
48
+ "@t8/store": "^1.3.3"
49
49
  }
50
50
  }