Skip to content

Commit c1d3356

Browse files
committed
feat: add atomTree utility
- createAtom - createAtom.remove - createAtom.getSubTree - createAtom.getNodePath
1 parent 1431682 commit c1d3356

File tree

4 files changed

+2175
-2270
lines changed

4 files changed

+2175
-2270
lines changed

README.md

+104
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,107 @@ const todoFamily = atomFamily(
109109
### Codesandbox
110110

111111
<CodeSandbox id="huxd4i" />
112+
113+
---
114+
115+
## atomTree
116+
117+
The **atomTree** utility provides a hierarchical way to create, reuse, and remove Jotai atoms. Each atom is associated with a unique path, which is an array of unknown types. When you request the same path multiple times, `atomTree` ensures that the same atom instance is returned. You can also remove a specific atom or an entire subtree of atoms when they are no longer needed.
118+
119+
Use `atomTree` when you anticipate a large number of potential paths and want to:
120+
121+
- **Reuse the same atom** for repeated paths.
122+
- **Clean up** unwanted atoms easily, including entire subtrees.
123+
124+
```js
125+
import { atom } from 'jotai'
126+
import { atomTree } from 'jotai-family'
127+
128+
// Create a tree instance, passing a factory function
129+
// that takes a path array and returns a new atom.
130+
const tree = atomTree((path) => atom(path.join('-')))
131+
132+
// Create or retrieve the atom at ['foo', 'bar']
133+
const atomA = tree(['foo', 'bar'])
134+
const atomB = tree(['foo', 'bar'])
135+
136+
// atomA and atomB are the same instance.
137+
console.log(atomA === atomB) // true
138+
139+
// Remove the atom at ['foo', 'bar']
140+
// (and optionally remove its entire subtree)
141+
tree.remove(['foo', 'bar'])
142+
```
143+
144+
### API
145+
146+
#### Creating the tree
147+
148+
Creates a new hierarchical tree of Jotai atoms. It accepts a **initializePathAtom** function that receives a path array and returns an atom. The returned function can be used to create, retrieve, and remove atoms at specific paths.
149+
150+
```ts
151+
function atomTree<Path, AtomType>(
152+
initializePathAtom: (path: Path) => AtomType
153+
): {
154+
(path: Path): AtomType
155+
remove(path: Path, removeSubTree?: boolean): void
156+
getSubTree(path: Path): Node<AtomType> | undefined
157+
getNodePath(path: Path): Node<AtomType>[]
158+
}
159+
160+
type Node<AtomType> = {
161+
atom?: AtomType
162+
children?: Map<PathSegment, Node<AtomType>>
163+
}
164+
```
165+
166+
### Creating Path Atoms
167+
```ts
168+
tree(path: Path): AtomType
169+
```
170+
Creates (or retrieves) an atom at the specified path. Subsequent calls with the same path return the same atom instance.
171+
172+
### Removing Path Atoms
173+
```ts
174+
tree.remove(path: Path, removeSubTree = false): void
175+
```
176+
Removes the atom at the specified path. If `removeSubTree` is `true`, all child paths under that path are also removed.
177+
178+
This method removes the atom at the specified path. If `removeSubTree` is `true`, it also removes all child paths under that path.
179+
180+
### Retrieving A Subtree
181+
```ts
182+
tree.getSubTree(path: Path): Node<AtomType> | undefined
183+
```
184+
185+
Retrieves the internal node representing the specified path. This is useful for inspecting the tree structure. The node structure is as follows:
186+
187+
```ts
188+
type Node<AtomType> = {
189+
atom?: AtomType
190+
children?: Map<PathSegment, Node<AtomType>>
191+
}
192+
```
193+
194+
### Retrieving A Node Path
195+
```ts
196+
tree.getNodePath(path: Path): Node<AtomType>[]
197+
```
198+
Returns an array of node objects from the root node to the node at the specified path, inclusive.
199+
200+
## Usage Example
201+
202+
```js
203+
import { atom } from 'jotai'
204+
import { atomTree } from 'jotai-family'
205+
206+
const btree = atomTree((path) => atom(`Data for path: ${path}`))
207+
208+
// Create or retrieve the atom at [true, false]
209+
const userAtom = btree([true, false])
210+
211+
console.log(store.get(userAtom)) // 'Data for path: true,false'
212+
213+
// Remove the atom (and optionally remove its subtree)
214+
btree.remove([true,false])
215+
```

0 commit comments

Comments
 (0)