UNPKG

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