diff --git a/README.md b/README.md
index eefa250..f16a736 100644
--- a/README.md
+++ b/README.md
@@ -139,18 +139,52 @@ const valuesAtom = withAtomEffect(atom(null), (get, set) => {
## Effect Behavior
-- **Cleanup Function:**
- The cleanup function is invoked on unmount or before re-evaluation.
+- **Executes Synchronously:**
+ `effect` runs synchronous in the current task after synchronous evaluations complete.
Example
```js
- atomEffect((get, set) => {
- const intervalId = setInterval(() => set(clockAtom, Date.now()))
- return () => clearInterval(intervalId)
+ const countAtom = atom(0)
+ const logAtom = atom('')
+ const logCounts = atomEffect((get, set) => {
+ set(logAtom, `count is now ${get(countAtom)}`)
+ })
+ const setCountAndReadLog = atom(null, async (get, set) => {
+ get(logAtom) // 'count is now 0'
+ set(countAtom, increment) // effect runs synchronously
+ get(logAtom) // 'count is now 1'
+ })
+ store.sub(logCounts, () => {})
+ store.set(setCountAndReadLog)
+ ```
+
+
+
+- **Batched Updates:**
+ Multiple synchronous updates are batched as a single atomic transaction.
+
+
+
+ Example
+
+ ```js
+ const tensAtom = atom(0)
+ const onesAtom = atom(0)
+ const updateTensAndOnes = atom(null, (get, set) => {
+ set(tensAtom, (value) => value + 1)
+ set(onesAtom, (value) => value + 1)
+ })
+ const combos = atom([])
+ const effectAtom = atomEffect((get, set) => {
+ const value = get(tensAtom) * 10 + get(onesAtom)
+ set(combos, (arr) => [...arr, value])
})
+ store.sub(effectAtom, () => {})
+ store.set(updateTensAndOnes)
+ store.get(combos) // [00, 11]
```
@@ -172,28 +206,24 @@ const valuesAtom = withAtomEffect(atom(null), (get, set) => {
-- **Supports Recursion:**
- Recursion is supported with `set.recurse` but not in cleanup.
+- **Cleanup Function:**
+ The cleanup function is invoked on unmount or before re-evaluation.
Example
```js
- const countAtom = atom(0)
atomEffect((get, set) => {
- const count = get(countAtom)
- const timeoutId = setTimeout(() => {
- set.recurse(countAtom, increment)
- }, 1000)
- return () => clearTimeout(timeoutId)
+ const intervalId = setInterval(() => set(clockAtom, Date.now()))
+ return () => clearInterval(intervalId)
})
```
-- **Supports Peek:**
- Use `get.peek` to read atom data without subscribing.
+- **Supports Recursion:**
+ Recursion is supported with `set.recurse` but not in cleanup.
@@ -202,14 +232,18 @@ const valuesAtom = withAtomEffect(atom(null), (get, set) => {
```js
const countAtom = atom(0)
atomEffect((get, set) => {
- const count = get.peek(countAtom) // Will not add countAtom as a dependency
+ const count = get(countAtom)
+ const timeoutId = setTimeout(() => {
+ set.recurse(countAtom, increment)
+ }, 1000)
+ return () => clearTimeout(timeoutId)
})
```
-- **Executes In The Next Microtask:**
- `effect` runs in the next available microtask after synchronous evaluations complete.
+- **Supports Peek:**
+ Use `get.peek` to read atom data without subscribing.
@@ -217,48 +251,33 @@ const valuesAtom = withAtomEffect(atom(null), (get, set) => {
```js
const countAtom = atom(0)
- const logAtom = atom('')
- const logCounts = atomEffect((get, set) => {
- set(logAtom, `count is now ${get(countAtom)}`)
- })
- const setCountAndReadLog = atom(null, async (get, set) => {
- get(logAtom) // 'count is now 0'
- set(countAtom, increment) // effect runs in next microtask
- get(logAtom) // 'count is now 0'
- await Promise.resolve()
- get(logAtom) // 'count is now 1'
+ atomEffect((get, set) => {
+ const count = get.peek(countAtom) // Will not add countAtom as a dependency
})
- store.sub(logCounts, () => {})
- store.set(setCountAndReadLog)
```
-- **Batched Updates:**
- Multiple synchronous updates are batched as a single atomic transaction.
+- **Idempotency:**
+ `atomEffect` runs once per state change, regardless of how many times it is referenced.
Example
```js
- const tensAtom = atom(0)
- const onesAtom = atom(0)
- const updateTensAndOnes = atom(null, (get, set) => {
- set(tensAtom, (value) => value + 1)
- set(onesAtom, (value) => value + 1)
- })
- const combos = atom([])
- const effectAtom = atomEffect((get, set) => {
- const value = get(tensAtom) * 10 + get(onesAtom)
- set(combos, (arr) => [...arr, value])
+ let i = 0
+ const effectAtom = atomEffect(() => {
+ get(countAtom)
+ i++
})
store.sub(effectAtom, () => {})
- store.set(updateTensAndOnes)
- store.get(combos) // [00, 11]
+ store.sub(effectAtom, () => {})
+ store.set(countAtom, increment)
+ console.log(i) // 1
```
-
+
- **Conditionally Running Effects:**
`atomEffect` only runs when mounted.
@@ -277,28 +296,6 @@ const valuesAtom = withAtomEffect(atom(null), (get, set) => {
-- **Idempotency:**
- `atomEffect` runs once per state change, regardless of how many times it is referenced.
-
-
-
- Example
-
- ```js
- let i = 0
- const effectAtom = atomEffect(() => {
- get(countAtom)
- i++
- })
- store.sub(effectAtom, () => {})
- store.sub(effectAtom, () => {})
- store.set(countAtom, increment)
- await Promise.resolve()
- console.log(i) // 1
- ```
-
-
-
## Dependency Management
Aside from mount events, the effect runs when any of its dependencies change value.
diff --git a/tests/atomEffect.test.ts b/tests/atomEffect.test.ts
index 92ef029..c28e595 100644
--- a/tests/atomEffect.test.ts
+++ b/tests/atomEffect.test.ts
@@ -1050,17 +1050,15 @@ it('should not run the effect when the effectAtom is unmounted', function test()
expect(runCount).toBe(0)
})
-it.only('should work in StrictMode', async () => {
+it('should work in StrictMode', function test() {
const watchedAtom = atom(0)
let runCount = 0
let cleanupCount = 0
- let deferred = createDeferred()
const effectAtom = atomEffect((get, set) => {
get(watchedAtom)
runCount++
console.log('effect', { runCount })
- deferred.resolve()
set(watchedAtom, (v) => v + 1)
return () => {
cleanupCount++