@ersbeth/picoflow 2.0.2 → 2.0.3
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 +10 -0
- package/SKILL.md +106 -0
- package/package.json +5 -1
- package/.gitlab-ci.yml +0 -24
- package/.vscode/settings.json +0 -5
- package/CHANGELOG.md +0 -94
- package/biome.json +0 -47
- package/docs/.vitepress/config.mts +0 -145
- package/docs/api/functions/array.md +0 -35
- package/docs/api/functions/constant.md +0 -33
- package/docs/api/functions/constantAsync.md +0 -69
- package/docs/api/functions/derivation.md +0 -34
- package/docs/api/functions/derivationAsync.md +0 -34
- package/docs/api/functions/from.md +0 -129
- package/docs/api/functions/isDisposable.md +0 -27
- package/docs/api/functions/map.md +0 -36
- package/docs/api/functions/signal.md +0 -21
- package/docs/api/functions/state.md +0 -67
- package/docs/api/functions/stateAsync.md +0 -69
- package/docs/api/functions/subscribe.md +0 -40
- package/docs/api/functions/writableDerivation.md +0 -33
- package/docs/api/functions/writableDerivationAsync.md +0 -34
- package/docs/api/index.md +0 -61
- package/docs/api/interfaces/FlowArray.md +0 -439
- package/docs/api/interfaces/FlowConstant.md +0 -220
- package/docs/api/interfaces/FlowConstantAsync.md +0 -221
- package/docs/api/interfaces/FlowDerivation.md +0 -241
- package/docs/api/interfaces/FlowDerivationAsync.md +0 -242
- package/docs/api/interfaces/FlowDisposable.md +0 -59
- package/docs/api/interfaces/FlowEffect.md +0 -64
- package/docs/api/interfaces/FlowMap.md +0 -374
- package/docs/api/interfaces/FlowObservable.md +0 -155
- package/docs/api/interfaces/FlowSignal.md +0 -156
- package/docs/api/interfaces/FlowState.md +0 -269
- package/docs/api/interfaces/FlowStateAsync.md +0 -268
- package/docs/api/interfaces/FlowSubscribable.md +0 -55
- package/docs/api/interfaces/FlowTracker.md +0 -61
- package/docs/api/interfaces/FlowValue.md +0 -222
- package/docs/api/interfaces/FlowWritableDerivation.md +0 -292
- package/docs/api/interfaces/FlowWritableDerivationAsync.md +0 -293
- package/docs/api/type-aliases/DerivationFunction.md +0 -28
- package/docs/api/type-aliases/DerivationFunctionAsync.md +0 -28
- package/docs/api/type-aliases/FlowArrayAction.md +0 -60
- package/docs/api/type-aliases/FlowDataTracker.md +0 -33
- package/docs/api/type-aliases/FlowMapAction.md +0 -48
- package/docs/api/type-aliases/FlowOnDataListener.md +0 -33
- package/docs/api/type-aliases/FlowOnErrorListener.md +0 -27
- package/docs/api/type-aliases/FlowOnPendingListener.md +0 -21
- package/docs/api/type-aliases/FlowReadonly.md +0 -22
- package/docs/api/type-aliases/InitFunction.md +0 -21
- package/docs/api/type-aliases/InitFunctionAsync.md +0 -21
- package/docs/api/type-aliases/NotPromise.md +0 -21
- package/docs/api/type-aliases/UpdateFunction.md +0 -27
- package/docs/api/type-aliases/UpdateFunctionAsync.md +0 -27
- package/docs/api/typedoc-sidebar.json +0 -65
- package/docs/examples/examples.md +0 -2311
- package/docs/examples/patterns.md +0 -649
- package/docs/guide/advanced/architecture.md +0 -1234
- package/docs/guide/advanced/disposal.md +0 -426
- package/docs/guide/advanced/migration-v1.md +0 -464
- package/docs/guide/advanced/migration-v2.md +0 -204
- package/docs/guide/advanced/solidjs.md +0 -135
- package/docs/guide/introduction/concepts.md +0 -57
- package/docs/guide/introduction/conventions.md +0 -30
- package/docs/guide/introduction/getting-started.md +0 -139
- package/docs/guide/introduction/lifecycle.md +0 -368
- package/docs/guide/primitives/array.md +0 -286
- package/docs/guide/primitives/constant.md +0 -207
- package/docs/guide/primitives/derivations.md +0 -281
- package/docs/guide/primitives/effects.md +0 -372
- package/docs/guide/primitives/map.md +0 -265
- package/docs/guide/primitives/overview.md +0 -92
- package/docs/guide/primitives/signal.md +0 -222
- package/docs/guide/primitives/state.md +0 -272
- package/docs/index.md +0 -47
- package/docs/public/logo.svg +0 -1
- package/src/api/base/flowDisposable.ts +0 -44
- package/src/api/base/flowObservable.ts +0 -28
- package/src/api/base/flowSubscribable.ts +0 -87
- package/src/api/base/flowTracker.ts +0 -7
- package/src/api/base/index.ts +0 -4
- package/src/api/index.ts +0 -2
- package/src/api/nodes/async/flowConstantAsync.ts +0 -36
- package/src/api/nodes/async/flowDerivationAsync.ts +0 -42
- package/src/api/nodes/async/flowStateAsync.ts +0 -47
- package/src/api/nodes/async/flowWritableDerivationAsync.ts +0 -33
- package/src/api/nodes/async/index.ts +0 -4
- package/src/api/nodes/collections/flowArray.ts +0 -155
- package/src/api/nodes/collections/flowMap.ts +0 -115
- package/src/api/nodes/collections/index.ts +0 -2
- package/src/api/nodes/flowEffect.ts +0 -42
- package/src/api/nodes/flowSignal.ts +0 -28
- package/src/api/nodes/flowValue.ts +0 -37
- package/src/api/nodes/index.ts +0 -7
- package/src/api/nodes/sync/flowConstant.ts +0 -33
- package/src/api/nodes/sync/flowDerivation.ts +0 -41
- package/src/api/nodes/sync/flowState.ts +0 -45
- package/src/api/nodes/sync/flowWritableDerivation.ts +0 -31
- package/src/api/nodes/sync/index.ts +0 -4
- package/src/api/nodes/utils.ts +0 -24
- package/src/base/disposable.ts +0 -18
- package/src/base/executionStack.ts +0 -42
- package/src/base/index.ts +0 -5
- package/src/base/node.ts +0 -98
- package/src/base/observable.ts +0 -92
- package/src/base/observer.ts +0 -51
- package/src/converters/index.ts +0 -1
- package/src/converters/solid.ts +0 -109
- package/src/index.ts +0 -2
- package/src/nodes/arrayNode.ts +0 -180
- package/src/nodes/effectNode.ts +0 -58
- package/src/nodes/index.ts +0 -7
- package/src/nodes/mapNode.ts +0 -125
- package/src/nodes/signalNode.ts +0 -19
- package/src/nodes/valueAsyncNode.ts +0 -85
- package/src/nodes/valueNode.ts +0 -148
- package/src/nodes/valueSyncNode.ts +0 -125
- package/src/schedulers/asyncResolver.ts +0 -78
- package/src/schedulers/asyncScheduler.ts +0 -66
- package/src/schedulers/index.ts +0 -4
- package/src/schedulers/pendingError.ts +0 -13
- package/src/schedulers/scheduler.ts +0 -9
- package/src/schedulers/syncResolver.ts +0 -69
- package/src/schedulers/syncScheduler.ts +0 -55
- package/test/base/pendingError.test.ts +0 -67
- package/test/converters/solid.derivation.browser.test.tsx +0 -69
- package/test/converters/solid.node.test.ts +0 -654
- package/test/converters/solid.state.browser.test.tsx +0 -1592
- package/test/reactivity/flowSignal.test.ts +0 -226
- package/test/reactivity/nodes/async/asyncScheduler/asyncResolver.test.ts +0 -593
- package/test/reactivity/nodes/async/asyncScheduler/asyncScheduler.test.ts +0 -317
- package/test/reactivity/nodes/async/flowConstantAsync.test.ts +0 -652
- package/test/reactivity/nodes/async/flowDerivation.test.ts +0 -898
- package/test/reactivity/nodes/async/flowDerivationAsync.test.ts +0 -1716
- package/test/reactivity/nodes/async/flowStateAsync.test.ts +0 -708
- package/test/reactivity/nodes/async/flowWritableDerivationAsync.test.ts +0 -614
- package/test/reactivity/nodes/collections/flowArray.asyncStates.test.ts +0 -1289
- package/test/reactivity/nodes/collections/flowArray.scalars.test.ts +0 -961
- package/test/reactivity/nodes/collections/flowArray.states.test.ts +0 -1035
- package/test/reactivity/nodes/collections/flowMap.asyncStates.test.ts +0 -960
- package/test/reactivity/nodes/collections/flowMap.scalars.test.ts +0 -775
- package/test/reactivity/nodes/collections/flowMap.states.test.ts +0 -958
- package/test/reactivity/nodes/sync/flowConstant.test.ts +0 -377
- package/test/reactivity/nodes/sync/flowDerivation.test.ts +0 -896
- package/test/reactivity/nodes/sync/flowState.test.ts +0 -341
- package/test/reactivity/nodes/sync/flowWritableDerivation.test.ts +0 -603
- package/test/vitest.d.ts +0 -10
- package/tsconfig.json +0 -37
- package/typedoc.json +0 -37
- package/vite.config.ts +0 -31
- package/vitest.browser.config.ts +0 -21
- package/vitest.config.ts +0 -17
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
# Use with SolidJS
|
|
2
|
-
|
|
3
|
-
PicoFlow provides seamless integration with SolidJS through the `@ersbeth/picoflow/solid` module. This integration allows you to use PicoFlow's reactive primitives within SolidJS components, combining PicoFlow's explicit tracking model with SolidJS's automatic dependency tracking.
|
|
4
|
-
|
|
5
|
-
## Why Use PicoFlow with SolidJS?
|
|
6
|
-
|
|
7
|
-
PicoFlow and SolidJS complement each other well:
|
|
8
|
-
|
|
9
|
-
- **PicoFlow** provides explicit control over reactivity with fine-grained tracking
|
|
10
|
-
- **SolidJS** offers automatic dependency tracking within components
|
|
11
|
-
- **Together** you get the best of both worlds: explicit control in your business logic and automatic reactivity in your UI
|
|
12
|
-
|
|
13
|
-
### When to Use This Integration
|
|
14
|
-
|
|
15
|
-
Use PicoFlow with SolidJS when:
|
|
16
|
-
|
|
17
|
-
- ✅ You want explicit control over reactivity in shared business logic
|
|
18
|
-
- ✅ You need fine-grained tracking (e.g., specific array operations)
|
|
19
|
-
- ✅ You're building a library that should work with multiple frameworks
|
|
20
|
-
- ✅ You want to share reactive logic between different UI frameworks
|
|
21
|
-
- ✅ You prefer PicoFlow's explicit tracking model for complex state management
|
|
22
|
-
|
|
23
|
-
Use pure SolidJS when:
|
|
24
|
-
|
|
25
|
-
- ✅ Your reactive logic is tightly coupled to components
|
|
26
|
-
- ✅ You prefer automatic dependency tracking everywhere
|
|
27
|
-
- ✅ You don't need fine-grained control over reactivity
|
|
28
|
-
|
|
29
|
-
## Installation
|
|
30
|
-
|
|
31
|
-
First, ensure you have both PicoFlow and SolidJS installed:
|
|
32
|
-
|
|
33
|
-
::: code-group
|
|
34
|
-
|
|
35
|
-
```bash [pnpm]
|
|
36
|
-
pnpm add @ersbeth/picoflow solid-js
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
```bash [npm]
|
|
40
|
-
npm install @ersbeth/picoflow solid-js
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
```bash [yarn]
|
|
44
|
-
yarn add @ersbeth/picoflow solid-js
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
:::
|
|
48
|
-
|
|
49
|
-
Then import the integration utilities:
|
|
50
|
-
|
|
51
|
-
```typescript
|
|
52
|
-
import { from } from '@ersbeth/picoflow/solid'
|
|
53
|
-
import { state, derivation, resource } from '@ersbeth/picoflow'
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## PicoFlow to SolidJS
|
|
57
|
-
|
|
58
|
-
The `from()` function converts PicoFlow observables into SolidJS primitives that work seamlessly in Solid components.
|
|
59
|
-
|
|
60
|
-
### Basic Conversion
|
|
61
|
-
|
|
62
|
-
Convert any PicoFlow observable to a Solid primitive:
|
|
63
|
-
|
|
64
|
-
```typescript
|
|
65
|
-
import { from } from '@ersbeth/picoflow/solid'
|
|
66
|
-
import { state } from '@ersbeth/picoflow'
|
|
67
|
-
|
|
68
|
-
// Create PicoFlow state
|
|
69
|
-
const $count = state(0)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
// Use in Solid component
|
|
73
|
-
function Counter() {
|
|
74
|
-
// Convert to Solid primitive
|
|
75
|
-
const count = from($count)
|
|
76
|
-
return <div>Count: {count()}</div>
|
|
77
|
-
}
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
The `from()` function uses SolidJS's `onMount` and `onCleanup` to properly dispose of the internal PicoFlow effects when the component unmounts. You don't need to manually dispose of converted primitives.
|
|
81
|
-
|
|
82
|
-
### Conversion Rules
|
|
83
|
-
|
|
84
|
-
The `from()` function automatically determines the right Solid primitive based on the value type:
|
|
85
|
-
|
|
86
|
-
| PicoFlow Input | Solid Output | When |
|
|
87
|
-
|----------------|--------------|------|
|
|
88
|
-
| `FlowObservable<T>` (non-Promise) | `SolidDerivation<T>` | Synchronous values |
|
|
89
|
-
| `FlowObservable<Promise<T>>` | `SolidResource<T>` | Asynchronous values |
|
|
90
|
-
| `(t) => T` (getter function) | `SolidDerivation<T>` | Synchronous computation |
|
|
91
|
-
| `(t) => Promise<T>` (getter function) | `SolidResource<T>` | Asynchronous computation |
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
## Complete Examples
|
|
95
|
-
|
|
96
|
-
```typescript
|
|
97
|
-
import { from } from '@ersbeth/picoflow/solid'
|
|
98
|
-
import { state, derivation } from '@ersbeth/picoflow'
|
|
99
|
-
|
|
100
|
-
// Create PicoFlow global state and derivation
|
|
101
|
-
const $count = state(0)
|
|
102
|
-
const $isEven = derivation((t) => $count.get(t) % 2 === 0)
|
|
103
|
-
|
|
104
|
-
// Use in component
|
|
105
|
-
function Counter() {
|
|
106
|
-
|
|
107
|
-
// Convert to Solid primitives
|
|
108
|
-
const count = from($count)
|
|
109
|
-
const isEven = from($isEven)
|
|
110
|
-
|
|
111
|
-
return (
|
|
112
|
-
<div>
|
|
113
|
-
<p>Count: {count()}</p>
|
|
114
|
-
<p>{isEven.get() ? 'Even' : 'Odd'}</p>
|
|
115
|
-
<button onClick={() => $count.set(prev => prev + 1)}>Increment</button>
|
|
116
|
-
<button onClick={() => $count.set(prev => prev - 1)}>Decrement</button>
|
|
117
|
-
</div>
|
|
118
|
-
)
|
|
119
|
-
}
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
## Best Practices
|
|
123
|
-
|
|
124
|
-
### When to Convert vs Use Directly
|
|
125
|
-
|
|
126
|
-
**Convert PicoFlow observables (`from()`) when:**
|
|
127
|
-
- ✅ You have existing PicoFlow state/logic to reuse
|
|
128
|
-
- ✅ You want to share reactive logic between frameworks
|
|
129
|
-
- ✅ You need fine-grained PicoFlow features (arrays, maps, streams)
|
|
130
|
-
- ✅ Your business logic is framework-agnostic
|
|
131
|
-
|
|
132
|
-
**Use Solid primitives directly when:**
|
|
133
|
-
- ✅ The state is only used in Solid components
|
|
134
|
-
- ✅ You don't need PicoFlow's advanced features
|
|
135
|
-
- ✅ You prefer SolidJS's automatic tracking for simple cases
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
# Concepts
|
|
2
|
-
|
|
3
|
-
Understand the fundamentals of reactive programming and how it simplifies managing your application's state and behavior.
|
|
4
|
-
|
|
5
|
-
## What is Reactive Programming?
|
|
6
|
-
|
|
7
|
-
Imagine a **spreadsheet** where you write `=A1 + B1` in cell C1. When you change A1 or B1, C1 automatically updates. That's reactive programming - values that automatically update when their dependencies change.
|
|
8
|
-
|
|
9
|
-
## Imperative Approach
|
|
10
|
-
|
|
11
|
-
In traditional programming, you manually update everything:
|
|
12
|
-
|
|
13
|
-
```typescript
|
|
14
|
-
// Imperative approach
|
|
15
|
-
let count = 0
|
|
16
|
-
let doubledCount = count * 2
|
|
17
|
-
|
|
18
|
-
function increment() {
|
|
19
|
-
count++
|
|
20
|
-
doubledCount = count * 2 // Must remember to update!
|
|
21
|
-
updateUI(count, doubledCount) // Must remember to update UI!
|
|
22
|
-
}
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
```mermaid
|
|
27
|
-
flowchart LR
|
|
28
|
-
A[count = 5] --> B[Manually update doubled]
|
|
29
|
-
B --> C[Manually update UI]
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
## Reactive Approach
|
|
33
|
-
|
|
34
|
-
With reactive programming, dependencies update automatically:
|
|
35
|
-
|
|
36
|
-
```typescript
|
|
37
|
-
// Reactive approach with PicoFlow
|
|
38
|
-
const $count = state(0)
|
|
39
|
-
const $doubled = derivation((t) => $count.get(t) * 2)
|
|
40
|
-
|
|
41
|
-
subscribe(
|
|
42
|
-
(t) => ({ count: $count.get(t), doubled: $doubled.get(t) }),
|
|
43
|
-
(data) => updateUI(data.count, data.doubled) // Runs automatically!
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
function increment() {
|
|
47
|
-
$count.set(n => n + 1) // Everything else updates automatically!
|
|
48
|
-
}
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
```mermaid
|
|
52
|
-
flowchart LR
|
|
53
|
-
A2[$count.set 5] --> C2[$doubled updates]
|
|
54
|
-
C2 --> D2[UI effect runs]
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
**The benefit:** You define relationships once, and they stay synchronized automatically!
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# Naming Convention
|
|
2
|
-
|
|
3
|
-
You'll see variables prefixed with `$` throughout PicoFlow examples:
|
|
4
|
-
|
|
5
|
-
```typescript
|
|
6
|
-
const $count = state(0)
|
|
7
|
-
const $double = derivation((t) => $count.get(t) * 2)
|
|
8
|
-
```
|
|
9
|
-
|
|
10
|
-
This is a **naming convention** to make reactive values stand out. It helps you quickly identify:
|
|
11
|
-
- Which values are reactive
|
|
12
|
-
- Which values will cause re-executions when changed
|
|
13
|
-
- Where your state lives
|
|
14
|
-
|
|
15
|
-
Think of `$` as a visual marker: "This value is special - it's reactive!"
|
|
16
|
-
|
|
17
|
-
### Examples
|
|
18
|
-
|
|
19
|
-
```typescript
|
|
20
|
-
// Reactive values - use $ prefix
|
|
21
|
-
const $userName = state('Alice')
|
|
22
|
-
const $userAge = state(25)
|
|
23
|
-
const $isAdult = derivation((t) => $userAge.get(t) >= 18)
|
|
24
|
-
|
|
25
|
-
// Plain values - no $ prefix
|
|
26
|
-
const currentName = await $userName.pick() // Snapshot of current value
|
|
27
|
-
const maxAge = 100 // Constant
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
# Getting Started
|
|
2
|
-
|
|
3
|
-
Welcome to PicoFlow! This guide will help you install PicoFlow and build your first reactive application in just a few minutes.
|
|
4
|
-
|
|
5
|
-
## Why PicoFlow?
|
|
6
|
-
|
|
7
|
-
PicoFlow is a lightweight reactive library with a focus on **explicit control** and **simplicity**. Unlike some reactive libraries that track everything automatically, PicoFlow gives you precise control over what is reactive and what isn't.
|
|
8
|
-
|
|
9
|
-
### Key Philosophy
|
|
10
|
-
|
|
11
|
-
1. **Explicit Tracking** - You decide what to track with `.get(t)`
|
|
12
|
-
2. **Fine-grained Control** - React to specific operations, not just "something changed"
|
|
13
|
-
3. **No Magic** - Simple, predictable behavior
|
|
14
|
-
4. **TypeScript First** - Full type safety and inference
|
|
15
|
-
|
|
16
|
-
## Installation
|
|
17
|
-
|
|
18
|
-
Install PicoFlow using your preferred package manager:
|
|
19
|
-
|
|
20
|
-
::: code-group
|
|
21
|
-
|
|
22
|
-
```bash [pnpm]
|
|
23
|
-
pnpm add @ersbeth/picoflow
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
```bash [npm]
|
|
27
|
-
npm install @ersbeth/picoflow
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
```bash [yarn]
|
|
31
|
-
yarn add @ersbeth/picoflow
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
:::
|
|
35
|
-
|
|
36
|
-
If you plan to use the SolidJS integration, install SolidJS as a peer dependency:
|
|
37
|
-
|
|
38
|
-
::: code-group
|
|
39
|
-
|
|
40
|
-
```bash [pnpm]
|
|
41
|
-
pnpm add solid-js
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
```bash [npm]
|
|
45
|
-
npm install solid-js
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
```bash [yarn]
|
|
49
|
-
yarn add solid-js
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
:::
|
|
53
|
-
|
|
54
|
-
Import the primitives you need:
|
|
55
|
-
|
|
56
|
-
```typescript
|
|
57
|
-
import { state, derivation, subscribe } from '@ersbeth/picoflow'
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
For SolidJS integration:
|
|
61
|
-
|
|
62
|
-
```typescript
|
|
63
|
-
import { from } from '@ersbeth/picoflow'
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
## Your First PicoFlow App
|
|
67
|
-
|
|
68
|
-
Let's build a simple counter with PicoFlow:
|
|
69
|
-
|
|
70
|
-
```typescript
|
|
71
|
-
import { state, derivation, subscribe } from '@ersbeth/picoflow'
|
|
72
|
-
|
|
73
|
-
// Create reactive state (prefix with $ by convention)
|
|
74
|
-
const $count = state(0)
|
|
75
|
-
|
|
76
|
-
// Create a computed value
|
|
77
|
-
const $isEven = derivation((t) => {
|
|
78
|
-
return $count.get(t) % 2 === 0
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
// React to changes
|
|
82
|
-
subscribe(
|
|
83
|
-
(t) => ({ count:$count.get(t), even:$isEven.get(t)}),
|
|
84
|
-
(data) => {
|
|
85
|
-
console.log(`Count is ${data.count}, which is ${data.even ? 'even' : 'odd'}`)
|
|
86
|
-
}
|
|
87
|
-
)
|
|
88
|
-
// Logs "Count is 0, which is even"
|
|
89
|
-
|
|
90
|
-
// Update the state
|
|
91
|
-
$count.set(1) // Logs: "Count is 1, which is odd"
|
|
92
|
-
$count.set(2) // Logs: "Count is 2, which is even"
|
|
93
|
-
$count.set(3) // Logs: "Count is 3, which is odd"
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
### What Just Happened?
|
|
97
|
-
|
|
98
|
-
1. **State** (`$count`) - Holds a mutable value
|
|
99
|
-
2. **Derivation** (`$isEven`) - Computes a value based on state
|
|
100
|
-
3. **Subscribe** - Creates an effect that runs automatically when dependencies change
|
|
101
|
-
4. **Data function** `(t) => ...` - Tracks dependencies and returns data
|
|
102
|
-
5. **Callback** `(data) => ...` - Performs side effects with the data
|
|
103
|
-
6. **`.get(t)`** - Reads a value AND creates a dependency
|
|
104
|
-
7. **`.set()`** - Updates state, triggering subscribers
|
|
105
|
-
|
|
106
|
-
### Data Flow
|
|
107
|
-
|
|
108
|
-
Here's what happens when you call `$count.set(1)`:
|
|
109
|
-
|
|
110
|
-
```mermaid
|
|
111
|
-
sequenceDiagram
|
|
112
|
-
participant User
|
|
113
|
-
participant $count
|
|
114
|
-
participant $isEven
|
|
115
|
-
participant Subscribe
|
|
116
|
-
|
|
117
|
-
User->>$count: set(1)
|
|
118
|
-
activate $count
|
|
119
|
-
Note over $count: Updates value 0 → 1
|
|
120
|
-
$count->>$isEven: notify()
|
|
121
|
-
Note over $isEven: Marks as dirty (lazy recompute)
|
|
122
|
-
$count->>Subscribe: notify()
|
|
123
|
-
deactivate $count
|
|
124
|
-
|
|
125
|
-
activate Subscribe
|
|
126
|
-
Note over Subscribe: Execute data function
|
|
127
|
-
Subscribe->>$count: get(t)
|
|
128
|
-
$count-->>Subscribe: 1
|
|
129
|
-
Subscribe->>$isEven: get(t)
|
|
130
|
-
activate $isEven
|
|
131
|
-
Note over $isEven: Recomputes because dirty
|
|
132
|
-
$isEven->>$count: get(t)
|
|
133
|
-
$count-->>$isEven: 1
|
|
134
|
-
$isEven-->>Subscribe: false
|
|
135
|
-
deactivate $isEven
|
|
136
|
-
Note over Subscribe: Call callback with {count: 1, even: false}
|
|
137
|
-
Note over Subscribe: Logs: "Count is 1, which is odd"
|
|
138
|
-
deactivate Subscribe
|
|
139
|
-
```
|