floppy-disk 3.0.0 → 3.0.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 (2) hide show
  1. package/README.md +61 -33
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -5,8 +5,6 @@ A lightweight, simple, and powerful state management library.
5
5
  This library was highly-inspired by [Zustand](https://www.npmjs.com/package/zustand) and [TanStack-Query](https://tanstack.com/query), they're awesome state manager.
6
6
  FloppyDisk provides a very similar developer experience (DX), while introducing additional features and a smaller bundle size.
7
7
 
8
- Comparison: https://github.com/afiiif/floppy-disk/tree/beta/comparison
9
-
10
8
  Demo: https://afiiif.github.io/floppy-disk/
11
9
 
12
10
  **Installation:**
@@ -23,7 +21,7 @@ Here's how to create and use a store:
23
21
  import { createStore } from 'floppy-disk/react';
24
22
 
25
23
  const useDigimon = createStore({
26
- age: 3,
24
+ age: 7,
27
25
  level: 'Rookie',
28
26
  });
29
27
  ```
@@ -41,10 +39,12 @@ function MyDigimon() {
41
39
  function Control() {
42
40
  return (
43
41
  <>
44
- <button onClick={() => {
45
- // You can setState directly
46
- useDigimon.setState(prev => ({ age: prev.age + 1 }));
47
- }}>
42
+ <button
43
+ onClick={() => {
44
+ // You can setState directly
45
+ useDigimon.setState((prev) => ({ age: prev.age + 1 }));
46
+ }}
47
+ >
48
48
  Increase digimon's age
49
49
  </button>
50
50
 
@@ -66,6 +66,43 @@ const evolve = () => {
66
66
  };
67
67
  ```
68
68
 
69
+ ### Store Subscription
70
+
71
+ At its core, FloppyDisk is a **pub-sub store**.
72
+
73
+ You can subscribe manually:
74
+
75
+ ```tsx
76
+ const unsubscribe = useMyStore.subscribe((state, prev) => {
77
+ console.log('New state:', state);
78
+ });
79
+
80
+ // Later
81
+ unsubscribe();
82
+ ```
83
+
84
+ FloppyDisk provides lifecycle hooks tied to subscription count.
85
+
86
+ ```tsx
87
+ const useTowerDefense = createStore(
88
+ { archers: 3, mages: 1, barracks: 2, artillery: 1 },
89
+ {
90
+ onFirstSubscribe: () => {
91
+ console.log('First subscriber! We’re officially popular 🎉');
92
+ },
93
+ onSubscribe: () => {
94
+ console.log('New subscriber joined. Welcome aboard 🫡');
95
+ },
96
+ onUnsubscribe: () => {
97
+ console.log('Subscriber left... was it something I said? 😭');
98
+ },
99
+ onLastUnsubscribe: () => {
100
+ console.log('Everyone left. Guess I’ll just exist quietly now...');
101
+ },
102
+ },
103
+ );
104
+ ```
105
+
69
106
  ### Differences from Zustand
70
107
 
71
108
  If you're coming from Zustand, this should feel very familiar.\
@@ -80,28 +117,28 @@ Key differences:
80
117
  Zustand examples:
81
118
 
82
119
  ```tsx
83
- const useExample1 = create(123);
120
+ const useDate = create(new Date(2021, 01, 11));
84
121
 
85
- const useExample2 = create(set => ({
122
+ const useCounter = create((set) => ({
86
123
  value: 1,
87
- inc: () => set(prev => ({ value: prev.value + 1 })),
124
+ increment: () => set((prev) => ({ value: prev.value + 1 })),
88
125
  }));
89
126
  ```
90
127
 
91
128
  FloppyDisk equivalents:
92
129
 
93
130
  ```tsx
94
- const useExample1 = createStore({ value: 123 });
131
+ const useDate = createStore({ value: new Date(2021, 01, 11) });
95
132
 
133
+ const useCounter = createStore({ value: 1 });
134
+ const increment = () => useCounter.setState((prev) => ({ value: prev.value + 1 }));
96
135
  // Unlike Zustand, defining actions inside the store is **discouraged** in FloppyDisk.
97
136
  // This improves tree-shakeability and keeps your store minimal.
98
- const useExample2 = createStore({ value: 1 });
99
- const inc = () => useExample2.setState(prev => ({ value: prev.value + 1 }));
100
137
 
101
- // However, it's still possible if you understand how closures work:
102
- const useExample2Alt = createStore({
138
+ // However, it's still possible to mix actions with the state if you understand how closures work:
139
+ const useCounterAlt = createStore({
103
140
  value: 1,
104
- inc: () => useExample2Alt.setState(prev => ({ value: prev.value + 1 })),
141
+ increment: () => useCounterAlt.setState((prev) => ({ value: prev.value + 1 })),
105
142
  });
106
143
  ```
107
144
 
@@ -272,14 +309,11 @@ type GetPostsResponse = {
272
309
  meta: { nextCursor: string };
273
310
  };
274
311
 
275
- const postsQuery = createQuery<GetPostsResponse, GetPostParams>(
276
- getPosts,
277
- {
278
- staleTime: Infinity,
279
- revalidateOnFocus: false,
280
- revalidateOnReconnect: false,
281
- },
282
- );
312
+ const postsQuery = createQuery<GetPostsResponse, GetPostParams>(getPosts, {
313
+ staleTime: Infinity,
314
+ revalidateOnFocus: false,
315
+ revalidateOnReconnect: false,
316
+ });
283
317
 
284
318
  function Main() {
285
319
  return <Page cursor={undefined} />;
@@ -294,12 +328,10 @@ function Page({ cursor }: { cursor?: string }) {
294
328
 
295
329
  return (
296
330
  <>
297
- {data.posts.map(post => (
331
+ {data.posts.map((post) => (
298
332
  <PostCard key={post.id} post={post} />
299
333
  ))}
300
- {data.meta.nextCursor && (
301
- <LoadMore nextCursor={data.meta.nextCursor} />
302
- )}
334
+ {data.meta.nextCursor && <LoadMore nextCursor={data.meta.nextCursor} />}
303
335
  </>
304
336
  );
305
337
  }
@@ -314,11 +346,7 @@ function LoadMore({ nextCursor }: { nextCursor?: string }) {
314
346
  return <Page cursor={nextCursor} />;
315
347
  }
316
348
 
317
- return (
318
- <ReachingBottomObserver
319
- onReachBottom={() => setIsNextPageRequested(true)}
320
- />
321
- );
349
+ return <BottomObserver onReachBottom={() => setIsNextPageRequested(true)} />;
322
350
  }
323
351
  ```
324
352
 
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "floppy-disk",
3
3
  "description": "Lightweight, simple, and powerful state management library",
4
4
  "private": false,
5
- "version": "3.0.0",
5
+ "version": "3.0.1",
6
6
  "keywords": [
7
7
  "utilities",
8
8
  "store",