@t8/react-store 1.0.36 → 1.0.38

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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # T8 React Store
2
2
 
3
- *Bare essentials for shared state management in React apps*
3
+ *Small React app state management lib aligned with React's state pattern, condensed to the essentials*
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
 
@@ -20,8 +20,8 @@
20
20
  ```
21
21
 
22
22
  - Similar to `useState()`
23
- - No boilerplate
24
23
  - Quick transition from local state
24
+ - No boilerplate
25
25
  - Easily integrates with Immer
26
26
  - SSR- and CSR-compatible
27
27
 
@@ -66,7 +66,7 @@ Moving the local state to the full-fledged shared state:
66
66
 
67
67
  🔹 The shared state setup shown above is very similar to `useState()` allowing for quick migration from local state to shared state or the other way around.
68
68
 
69
- 🔹 The `false` parameter in `useStore(store, false)` (as in `<ResetButton>` above) tells the hook not to subscribe the component to tracking the store state updates. The common use case is when a component makes use of the store state setter without using the store state value.
69
+ 🔹 The optional `false` parameter in `useStore(store, false)` (as in `<ResetButton>` above) tells the hook not to subscribe the component to tracking the store state updates. The common use case is when a component makes use of the store state setter without using the store state value.
70
70
 
71
71
  🔹 Similarly to instances of the built-in data container classes, such as `Set` and `Map`, stores are created as `new Store(data)` rather than with a factory function.
72
72
 
@@ -84,19 +84,16 @@ When only the store state setter is required, without the store state value, we
84
84
  let [, setState] = useState(store, false);
85
85
  ```
86
86
 
87
- Apart from a boolean, `useStore(store, shouldUpdate)` accepts a function of `(nextState, prevState) => boolean` as the second parameter to filter store updates to respond to:
87
+ Apart from a boolean, `useStore(store, shouldUpdate)` accepts a function of `(nextState, prevState) => boolean` as the optional second parameter to filter store updates to respond to:
88
88
 
89
89
  ```jsx
90
90
  import { useStore } from "@t8/react-store";
91
91
 
92
92
  let ItemCard = ({ id }) => {
93
- // Definition of changes in the item
94
- let hasRelevantUpdates = useCallback((nextItems, prevItems) => {
93
+ let [items, setItems] = useStore(itemStore, (nextItems, prevItems) => {
95
94
  // Assuming that items have a `revision` property
96
95
  return nextItems[id].revision !== prevItems[id].revision;
97
- }, [id]);
98
-
99
- let [items, setItems] = useStore(itemStore, hasRelevantUpdates);
96
+ });
100
97
 
101
98
  return (
102
99
  // Content
@@ -104,6 +101,8 @@ let ItemCard = ({ id }) => {
104
101
  };
105
102
  ```
106
103
 
104
+ While `useStore(itemStore)` in this component would trigger a re-render in response to any changes in the `itemStore` (which can be fine with a small store), with `useStore(itemStore, shouldUpdate)` the `ItemCard` component has a more targeted subscription to the store: in this example, a re-render will only be triggered if the `revision` property of the item with the given `id` has changed.
105
+
107
106
  ## Providing shared state
108
107
 
109
108
  Shared state can be provided to the app by means of a regular React Context provider:
@@ -156,7 +155,7 @@ let ItemCard = ({ id }) => {
156
155
 
157
156
  ## Store data
158
157
 
159
- A store can contain data of any type. With TypeScript, the type of a store containing data of type `T` is `Store<T>` which can be inferred from the data passed to `new Store(data)`.
158
+ A store can contain data of any type. With TypeScript, the type of a store containing data of type `T` is `Store<T>` which can be inferred from `data` passed to `new Store(data)`.
160
159
 
161
160
  Live demos:<br>
162
161
  [Primitive value state](https://codesandbox.io/p/sandbox/rtng37?file=%2Fsrc%2FPlusButton.jsx)<br>
@@ -2,24 +2,31 @@ import { type Store } from "@t8/store";
2
2
  export type SetStoreState<T> = Store<T>["setState"];
3
3
  export type ShouldUpdateCallback<T> = (nextState: T, prevState: T) => boolean;
4
4
  export type ShouldUpdate<T> = boolean | ShouldUpdateCallback<T>;
5
- export declare function useStore<T>(store: Store<T>,
6
5
  /**
7
- * Controls whether the component should be updated in response
8
- * to the store updates.
6
+ * Returns the state value of `store` passed as the parameter and
7
+ * a function to update the store state value.
9
8
  *
10
- * @defaultValue `true`
9
+ * @example
10
+ * ```js
11
+ * let [value, setValue] = useStore(store);
12
+ * ```
13
+ *
14
+ * The optional second parameter `shouldUpdate` controls whether
15
+ * the component using this hook should be updated in response to
16
+ * the store updates, which is set to `true` by default.
11
17
  *
12
18
  * `shouldUpdate` can be set to `false` to prevent subscription
13
- * to the store updates. Use case: when the component only requires
19
+ * to the store updates. Use case: if the component only requires
14
20
  * the store state setter but not the store state value, the
15
- * component may not need to respond to the store updates:
21
+ * component may not need to respond to the store updates at all:
16
22
  *
17
- * ```ts
23
+ * @example
24
+ * ```js
18
25
  * let [, setValue] = useStore(store, false);
19
26
  * ```
20
27
  *
21
- * `shouldUpdate` can be set to a function `(nextState, prevState) => boolean`
28
+ * `shouldUpdate` can also be a function `(nextState, prevState) => boolean`
22
29
  * to make the component respond only to specific store state changes,
23
30
  * when this function returns `true`.
24
31
  */
25
- shouldUpdate?: ShouldUpdate<T>): [T, SetStoreState<T>];
32
+ export declare function useStore<T>(store: Store<T>, shouldUpdate?: ShouldUpdate<T>): [T, SetStoreState<T>];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@t8/react-store",
3
- "version": "1.0.36",
4
- "description": "Bare essentials for shared state management in React apps",
3
+ "version": "1.0.38",
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",
7
7
  "type": "module",
@@ -11,11 +11,10 @@
11
11
  "compile": "npx esbuild index.ts --bundle --outdir=dist --platform=neutral --external:react",
12
12
  "demo": "npx @t8/serve 3000 * tests/counter -b src/index.tsx",
13
13
  "prepublishOnly": "npm run build",
14
- "preversion": "npx npm-run-all typecheck shape build test",
15
- "shape": "npx codeshape",
14
+ "preversion": "npx npm-run-all shape build test",
15
+ "shape": "npx codeshape --typecheck",
16
16
  "test": "npx playwright test --project=chromium",
17
17
  "tic-tac-toe": "npx @t8/serve 3000 * tests/tic-tac-toe -b src/index.tsx",
18
- "typecheck": "tsc --noEmit",
19
18
  "types": "tsc -p tsconfig.build.json"
20
19
  },
21
20
  "repository": {
@@ -37,12 +36,12 @@
37
36
  },
38
37
  "devDependencies": {
39
38
  "@playwright/test": "^1.56.0",
40
- "@t8/serve": "^0.1.34",
39
+ "@t8/serve": "^0.1.36",
41
40
  "@types/node": "^24.5.2",
42
- "@types/react": "^19.1.10",
43
- "@types/react-dom": "^19.1.9",
44
- "immer": "^10.1.3",
45
- "react-dom": "^19.1.1",
41
+ "@types/react": "^19.2.7",
42
+ "@types/react-dom": "^19.2.3",
43
+ "immer": "^11.0.1",
44
+ "react-dom": "^19.2.1",
46
45
  "typescript": "^5.9.3"
47
46
  },
48
47
  "dependencies": {
package/src/useStore.ts CHANGED
@@ -5,27 +5,35 @@ export type SetStoreState<T> = Store<T>["setState"];
5
5
  export type ShouldUpdateCallback<T> = (nextState: T, prevState: T) => boolean;
6
6
  export type ShouldUpdate<T> = boolean | ShouldUpdateCallback<T>;
7
7
 
8
+ /**
9
+ * Returns the state value of `store` passed as the parameter and
10
+ * a function to update the store state value.
11
+ *
12
+ * @example
13
+ * ```js
14
+ * let [value, setValue] = useStore(store);
15
+ * ```
16
+ *
17
+ * The optional second parameter `shouldUpdate` controls whether
18
+ * the component using this hook should be updated in response to
19
+ * the store updates, which is set to `true` by default.
20
+ *
21
+ * `shouldUpdate` can be set to `false` to prevent subscription
22
+ * to the store updates. Use case: if the component only requires
23
+ * the store state setter but not the store state value, the
24
+ * component may not need to respond to the store updates at all:
25
+ *
26
+ * @example
27
+ * ```js
28
+ * let [, setValue] = useStore(store, false);
29
+ * ```
30
+ *
31
+ * `shouldUpdate` can also be a function `(nextState, prevState) => boolean`
32
+ * to make the component respond only to specific store state changes,
33
+ * when this function returns `true`.
34
+ */
8
35
  export function useStore<T>(
9
36
  store: Store<T>,
10
- /**
11
- * Controls whether the component should be updated in response
12
- * to the store updates.
13
- *
14
- * @defaultValue `true`
15
- *
16
- * `shouldUpdate` can be set to `false` to prevent subscription
17
- * to the store updates. Use case: when the component only requires
18
- * the store state setter but not the store state value, the
19
- * component may not need to respond to the store updates:
20
- *
21
- * ```ts
22
- * let [, setValue] = useStore(store, false);
23
- * ```
24
- *
25
- * `shouldUpdate` can be set to a function `(nextState, prevState) => boolean`
26
- * to make the component respond only to specific store state changes,
27
- * when this function returns `true`.
28
- */
29
37
  shouldUpdate: ShouldUpdate<T> = true,
30
38
  ): [T, SetStoreState<T>] {
31
39
  if (!isStore(store)) throw new Error("'store' is not an instance of Store");