UNPKG

5.97 kBMarkdownView Raw
1<p align="center">
2 <a id="cover" href="#cover"><img src="img/cover.svg" alt="Jotai Primitive and flexible state management for React.
3 No extra re-renders, state resides within React, you get full benefits from suspense, and concurrent mode.
4 It's scalable from a simple React.useState replacement up to a large application with complex requirements.
5 npm i jotai" /></a>
6</p>
7
8[![Build Status](https://img.shields.io/github/workflow/status/react-spring/jotai/Lint?style=flat&colorA=000000&colorB=000000)](https://github.com/react-spring/jotai/actions?query=workflow%3ALint)
9[![Build Size](https://img.shields.io/bundlephobia/min/jotai?label=bundle%20size&style=flat&colorA=000000&colorB=000000)](https://bundlephobia.com/result?p=jotai)
10[![Version](https://img.shields.io/npm/v/jotai?style=flat&colorA=000000&colorB=000000)](https://www.npmjs.com/package/jotai)
11[![Downloads](https://img.shields.io/npm/dt/jotai.svg?style=flat&colorA=000000&colorB=000000)](https://www.npmjs.com/package/jotai)
12
13Jotai is pronounced "joe-tie" and means "state" in Japanese.
14
15You can try a live demo [here](https://codesandbox.io/s/jotai-demo-47wvh)
16and [there](https://codesandbox.io/s/jotai-demo-forked-x2g5d).
17
18#### How does Jotai differ from Recoil?
19
20* Minimalistic API
21* No string keys
22* TypeScript oriented
23
24<a id="firstcreateaprimitiveatom" href="#firstcreateaprimitiveatom"><img src="img/doc.01.svg" alt="First create a primitive atom" /></a>
25
26An atom represents a piece of state. All you need is to specify an initial value, which can be primitive values like strings and numbers, objects and arrays. You can create as many primitive atoms as you want.
27
28```jsx
29import { atom } from 'jotai'
30
31const countAtom = atom(0)
32const countryAtom = atom("Japan")
33const citiesAtom = atom(["Tokyo", "Kyoto", "Osaka"])
34const mangaAtom = atom({ "Dragon Ball": 1984, "One Piece": 1997, "Naruto": 1999 })
35```
36
37<a id="wrapyourcomponenttree" href="#wrapyourcomponenttree"><img src="img/doc.02.svg" alt="Wrap your component tree with Jotai's Provider" /></a>
38
39You can only use atoms under this component tree.
40
41```jsx
42import { Provider } from 'jotai'
43
44const Root = () => (
45 <Provider>
46 <App />
47 </Provider>
48)
49```
50
51<a id="usetheatom" href="#usetheatom"><img src="img/doc.03.svg" alt="Use the atom in your components" /></a>
52
53It can be used just like `React.useState`:
54
55```jsx
56import { useAtom } from 'jotai'
57
58function Counter() {
59 const [count, setCount] = useAtom(countAtom)
60 return (
61 <h1>
62 {count}
63 <button onClick={() => setCount(c => c + 1)}>one up</button>
64```
65
66<a id="derivedatomswithcomputedvalues" href="#derivedatomswithcomputedvalues"><img src="img/doc.04.svg" alt="Create derived atoms with computed values" /></a>
67
68A new read-only atom can be created from existing atoms by passing a read function as the first argument. `get` allows you to fetch the contextual value of any atom.
69
70```jsx
71const doubledCountAtom = atom(get => get(countAtom) * 2)
72
73function DoubleCounter() {
74 const [doubledCount] = useAtom(doubledCountAtom)
75 return <h2>{doubledCount}</h2>
76```
77
78<a id="recipes" href="#recipes"><img src="img/rec.00.svg" alt="Recipes" /></a>
79
80<a id="multipleatoms" href="#multipleatoms"><img src="img/rec.01.svg" alt="Creating an atom from multiple atoms" /></a>
81
82You can combine multiple atoms to create a derived atom.
83
84```jsx
85const count1 = atom(1)
86const count2 = atom(2)
87const count3 = atom(3)
88
89const sum = atom(get => get(count1) + get(count2) + get(count3))
90```
91
92Or if you like fp patterns ...
93
94```jsx
95const atoms = [count1, count2, count3, ...otherAtoms]
96const sum = atom(get => atoms.map(get).reduce((acc, count) => acc + count))
97```
98
99<a id="derivedasyncatoms" href="#derivedasyncatoms"><img src="img/rec.02.svg" alt="Derived async atoms (needs suspense)" /></a>
100
101You can make the read function an async function, too.
102
103```jsx
104const urlAtom = atom("https://json.host.com")
105const fetchUrlAtom = atom(
106 async get => {
107 const response = await fetch(get(urlAtom))
108 return await response.json()
109 }
110)
111
112function Status() {
113 // Re-renders the component after urlAtom changed and the async function above concludes
114 const [json] = useAtom(fetchUrlAtom)
115```
116
117<a id="writabledrivedatom" href="#writabledrivedatom"><img src="img/rec.03.svg" alt="You can create a writable derived atom" /></a>
118
119Specify a write function at the second argument. `get` will return the current value of an atom, `set` will update an atoms value.
120
121```jsx
122const decrementCountAtom = atom(
123 get => get(countAtom),
124 (get, set, _arg) => set(countAtom, get(countAtom) - 1),
125)
126
127function Counter() {
128 const [count, decrement] = useAtom(decrementCountAtom)
129 return (
130 <h1>
131 {count}
132 <button onClick={decrement}>Decrease</button>
133```
134
135<a id="writeonlyatoms" href="#writeonlyatoms"><img src="img/rec.04.svg" alt="Write only atoms" /></a>
136
137Just do not define a read function.
138
139```jsx
140const multiplyCountAtom = atom(null, (get, set, by) => set(countAtom, get(countAtom) * by))
141
142function Controls() {
143 const [, multiply] = useAtom(multiplyCountAtom)
144 return <button onClick={() => multiply(3)}>triple</button>
145```
146
147<a id="asyncactions" href="#asyncactions"><img src="img/rec.05.svg" alt="Async actions (needs suspense)" /></a>
148
149Just make the write function an async function and call `set` when you're ready.
150
151```jsx
152const fetchCountAtom = atom(
153 get => get(countAtom),
154 async (_get, set, url) => {
155 const response = await fetch(url)
156 set(countAtom, (await response.json()).count)
157 }
158)
159
160function Controls() {
161 const [count, compute] = useAtom(fetchCountAtom)
162 return <button onClick={() => compute("http://count.host.com")}>compute</button>
163```
164
165----
166
167## More information
168
169We will be organizing some more information later. Meanwhile, please see WIP materials in the issues.
170- [Utils Doc](./docs/utils.md)
171- [Example code snippets](https://github.com/react-spring/jotai/labels/has%20snippet)
172- [API Doc draft](https://github.com/react-spring/jotai/issues/27)