Skip to content

Commit

Permalink
feat: get.peek reads atom value without subscribing to updates
Browse files Browse the repository at this point in the history
  • Loading branch information
David Maskasky committed Jan 30, 2024
1 parent c3638ba commit dc1427e
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 4 deletions.
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ npm i jotai-effect
type CleanupFn = () => void

type EffectFn = (
get: Getter,
get: Getter & { peek: Getter },
set: Setter & { recurse: Setter },
) => CleanupFn | void

Expand Down Expand Up @@ -107,6 +107,9 @@ function MyComponent() {
set(countAtom, increment)
})
```

</details>

- **Supports Recursion:**
Recursion is supported with `set.recurse` for both sync and async use cases, but is not supported in the cleanup function.

Expand All @@ -128,6 +131,23 @@ function MyComponent() {

</details>

- **Supports Peek:**
Read atom data without subscribing to changes with `get.peek`.

<!-- prettier-ignore -->
<details style="cursor: pointer; user-select: none;">
<summary>Example</summary>

```js
const countAtom = atom(0)
atomEffect((get, set) => {
// will not rerun when countAtom changes
const count = get.peek(countAtom)
})
```

</details>

- **Executes In The Next Microtask:**
`effectFn` runs in the next available microtask, after all Jotai synchronous read evaluations have completed.

Expand Down
11 changes: 8 additions & 3 deletions src/atomEffect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import type { Atom, Getter, Setter } from 'jotai/vanilla'
import { atom } from 'jotai/vanilla'

type CleanupFn = () => void

type GetterWithPeek = Getter & { peek: Getter }
type SetterWithRecurse = Setter & { recurse: Setter }

export function atomEffect(
effectFn: (get: Getter, set: SetterWithRecurse) => void | CleanupFn
effectFn: (get: GetterWithPeek, set: SetterWithRecurse) => void | CleanupFn
) {
const refAtom = atom(() => ({
mounted: false,
Expand All @@ -17,6 +17,7 @@ export function atomEffect(
recursing: false,
refresh: () => {},
refreshing: false,
get: (() => {}) as Getter,
set: (() => {}) as Setter,
}))

Expand All @@ -26,6 +27,7 @@ export function atomEffect(
const ref = get(refAtom)
ref.mounted = mounted
if (mounted) {
ref.get = get
ref.set = set
ref.refresh = () => {
try {
Expand Down Expand Up @@ -60,11 +62,14 @@ export function atomEffect(
return ref.promise
}
const currDeps = new Map<Atom<unknown>, unknown>()
const getter: Getter = (a) => {
const getter: GetterWithPeek = (a) => {
const value = get(a)
currDeps.set(a, value)
return value
}
getter.peek = (anAtom) => {
return ref.get(anAtom)
}
const setter: SetterWithRecurse = (...args) => {
try {
++ref.inProgress
Expand Down

0 comments on commit dc1427e

Please sign in to comment.