|
1 | 1 | --- |
2 | 2 | title: History |
3 | | -description: A Jōtai utility package for advanced state history management |
4 | | -nav: 5.02 |
5 | | -keywords: history,undo,redo,jotai |
| 3 | +description: A Jōtai utility package for state history |
| 4 | +nav: 4.04 |
| 5 | +keywords: history, undo, redo, track changes |
6 | 6 | --- |
7 | 7 |
|
8 | | -[jotai-history](https://github.com/jotaijs/jotai-history) is a utility package for advanced state history management. |
| 8 | +[jotai-history](https://github.com/jotaijs/jotai-history) is a utility package for tracking state history in Jotai. |
9 | 9 |
|
10 | | -## install |
| 10 | +## Installation |
11 | 11 |
|
12 | 12 | ``` |
13 | 13 | npm install jotai-history |
14 | 14 | ``` |
15 | 15 |
|
16 | | -## withHistory |
| 16 | +## `withHistory` |
17 | 17 |
|
18 | | -### Signature |
19 | | - |
20 | | -```ts |
21 | | -declare function withHistory<T>(targetAtom: Atom<T>, limit: number): Atom<T[]> |
22 | | -``` |
| 18 | +```js |
| 19 | +import { withHistory } from 'jotai-history' |
23 | 20 |
|
24 | | -This function creates an atom that keeps a history of states for a given `targetAtom`. The `limit` parameter determines the maximum number of history states to keep. |
25 | | -This is useful for tracking the changes over time. |
| 21 | +const targetAtom = atom(0) |
| 22 | +const limit = 2 |
| 23 | +const historyAtom = withHistory(targetAtom, limit) |
26 | 24 |
|
27 | | -The history atom tracks changes to the `targetAtom` and maintains a list of previous states up to the specified `limit`. When the `targetAtom` changes, its new state is added to the history. |
| 25 | +function Component() { |
| 26 | + const [current, previous] = useAtomValue(historyAtom) |
| 27 | + ... |
| 28 | +} |
| 29 | +``` |
28 | 30 |
|
29 | | -### Usage |
| 31 | +### Description |
30 | 32 |
|
31 | | -```jsx |
32 | | -import { atom, useAtomValue, useSetAtom } from 'jotai' |
33 | | -import { withHistory } from 'jotai-history' |
| 33 | +`withHistory` creates an atom that tracks the history of states for a given `targetAtom`. The most recent `limit` states are retained. |
34 | 34 |
|
35 | | -const countAtom = atom(0) |
36 | | -const countWithPrevious = withHistory(countAtom, 2) |
| 35 | +### Action Symbols |
37 | 36 |
|
38 | | -function CountComponent() { |
39 | | - const [count, previousCount] = useAtomValue(countWithPrevious) |
40 | | - const setCount = useSetAtom(countAtom) |
| 37 | +- **RESET** |
| 38 | + Clears the entire history, removing all previous states (including the undo/redo stack). |
41 | 39 |
|
42 | | - return ( |
43 | | - <> |
44 | | - <p>Count: {count}</p> |
45 | | - <p>Previous Count: {previousCount}</p> |
46 | | - <button onClick={() => setCount((c) => c + 1)}>Increment</button> |
47 | | - </> |
48 | | - ) |
49 | | -} |
50 | | -``` |
| 40 | + ```js |
| 41 | + import { RESET } from 'jotai-history' |
51 | 42 |
|
52 | | -## withUndo |
| 43 | + ... |
53 | 44 |
|
54 | | -### Signature |
| 45 | + function Component() { |
| 46 | + const setHistoryAtom = useSetAtom(historyAtom) |
| 47 | + ... |
| 48 | + setHistoryAtom(RESET) |
| 49 | + } |
| 50 | + ``` |
55 | 51 |
|
56 | | -```ts |
57 | | -type Undoable = { |
58 | | - undo: () => void |
59 | | - redo: () => void |
60 | | - canUndo: boolean |
61 | | - canRedo: boolean |
62 | | -} |
63 | | -declare function withUndo<T>( |
64 | | - targetAtom: WritableAtom<T, [T], any>, |
65 | | - limit: number, |
66 | | -): Atom<Undoable> |
67 | | -``` |
| 52 | +- **UNDO** and **REDO** |
| 53 | + Moves the `targetAtom` backward or forward in its history. |
68 | 54 |
|
69 | | -`withHistory` provides undo and redo capabilities for an atom. It keeps track of the value history of `targetAtom` and provides methods to move back and forth through that history. |
| 55 | + ```js |
| 56 | + import { REDO, UNDO } from 'jotai-history' |
70 | 57 |
|
71 | | -The returned object includes: |
| 58 | + ... |
72 | 59 |
|
73 | | -- `undo`: A function to revert to the previous state. |
74 | | -- `redo`: A function to advance to the next state. |
75 | | -- `canUndo`: A boolean indicating if it's possible to undo. |
76 | | -- `canRedo`: A boolean indicating if it's possible to redo. |
| 60 | + function Component() { |
| 61 | + const setHistoryAtom = useSetAtom(historyAtom) |
| 62 | + ... |
| 63 | + setHistoryAtom(UNDO) |
| 64 | + setHistoryAtom(REDO) |
| 65 | + } |
| 66 | + ``` |
77 | 67 |
|
78 | | -### Usage |
| 68 | +### Indicators |
79 | 69 |
|
80 | | -```jsx |
81 | | -import { atom, useAtom, useAtomValue } from 'jotai' |
82 | | -import { withUndo } from 'jotai-history' |
| 70 | +- **canUndo** and **canRedo** |
| 71 | + Booleans indicating whether undo or redo actions are currently possible. These can be used to disable buttons or conditionally trigger actions. |
83 | 72 |
|
84 | | -const counterAtom = atom(0) |
85 | | -const undoCounterAtom = withUndo(counterAtom, 5) |
| 73 | + ```jsx |
| 74 | + ... |
86 | 75 |
|
87 | | -function CounterComponent() { |
88 | | - const { undo, redo, canUndo, canRedo } = useAtomValue(undoCounterAtom) |
89 | | - const [value, setValue] = useAtom(counterAtom) |
| 76 | + function Component() { |
| 77 | + const history = useAtomValue(historyAtom) |
90 | 78 |
|
91 | | - return ( |
92 | | - <> |
93 | | - <p>Count: {value}</p> |
94 | | - <button onClick={() => setValue((c) => c + 1)}>Increment</button> |
95 | | - <button onClick={undo} disabled={!canUndo}> |
96 | | - Undo |
97 | | - </button> |
98 | | - <button onClick={redo} disabled={!canRedo}> |
99 | | - Redo |
100 | | - </button> |
101 | | - </> |
102 | | - ) |
103 | | -} |
104 | | -``` |
| 79 | + return ( |
| 80 | + <> |
| 81 | + <button disabled={!history.canUndo}>Undo</button> |
| 82 | + <button disabled={!history.canRedo}>Redo</button> |
| 83 | + </> |
| 84 | + ) |
| 85 | + } |
| 86 | + ``` |
105 | 87 |
|
106 | 88 | <CodeSandbox id="g6qj3q" /> |
107 | 89 |
|
108 | 90 | ## Memory Management |
109 | 91 |
|
110 | | -⚠️ Since `withHistory` and `withUndo` keeps a history of states, it's important to manage memory by setting a reasonable `limit`. Excessive history can lead to memory bloat, especially in applications with frequent state updates. |
| 92 | +> Because `withHistory` maintains a list of previous states, be mindful of memory usage by setting a reasonable `limit`. Applications that update state frequently can grow significantly in memory usage. |
0 commit comments