UNPKG

6.5 kBMarkdownView Raw
1<br>
2
3![Jotai (light mode)](./img/jotai-header-light.png#gh-light-mode-only)
4![Jotai (dark mode)](./img/jotai-header-dark.png#gh-dark-mode-only)
5
6<br>
7
8`npm i jotai` or visit [jotai.org](https://jotai.org)
9
10[![Build Status](https://img.shields.io/github/workflow/status/pmndrs/jotai/Lint?style=flat&colorA=000000&colorB=000000)](https://github.com/pmndrs/jotai/actions?query=workflow%3ALint)
11[![Build Size](https://img.shields.io/bundlephobia/minzip/jotai?label=bundle%20size&style=flat&colorA=000000&colorB=000000)](https://bundlephobia.com/result?p=jotai)
12[![Version](https://img.shields.io/npm/v/jotai?style=flat&colorA=000000&colorB=000000)](https://www.npmjs.com/package/jotai)
13[![Downloads](https://img.shields.io/npm/dt/jotai.svg?style=flat&colorA=000000&colorB=000000)](https://www.npmjs.com/package/jotai)
14[![Discord Shield](https://img.shields.io/discord/740090768164651008?style=flat&colorA=000000&colorB=000000&label=discord&logo=discord&logoColor=ffffff)](https://discord.gg/poimandres)
15[![Open Collective](https://img.shields.io/opencollective/all/jotai?style=flat&colorA=000000&colorB=000000)](https://opencollective.com/jotai)
16
17Jotai is pronounced "joe-tie" and means "state" in Japanese.
18
19You can try live demos in the following:
20[Demo 1](https://codesandbox.io/s/jotai-demo-47wvh) |
21[Demo 2](https://codesandbox.io/s/jotai-demo-forked-x2g5d).
22
23#### How does Jotai differ from Recoil?
24
25- Minimalistic API
26- No string keys
27- TypeScript oriented
28
29### First create a primitive atom
30
31An atom represents a piece of state. All you need is to specify an initial
32value, which can be primitive values like strings and numbers, objects and
33arrays. You can create as many primitive atoms as you want.
34
35```jsx
36import { atom } from 'jotai'
37
38const countAtom = atom(0)
39const countryAtom = atom('Japan')
40const citiesAtom = atom(['Tokyo', 'Kyoto', 'Osaka'])
41const mangaAtom = atom({ 'Dragon Ball': 1984, 'One Piece': 1997, Naruto: 1999 })
42```
43
44### Use the atom in your components
45
46It can be used like `React.useState`:
47
48```jsx
49import { useAtom } from 'jotai'
50
51function Counter() {
52 const [count, setCount] = useAtom(countAtom)
53 return (
54 <h1>
55 {count}
56 <button onClick={() => setCount(c => c + 1)}>one up</button>
57```
58
59### Create derived atoms with computed values
60
61A new read-only atom can be created from existing atoms by passing a read
62function as the first argument. `get` allows you to fetch the contextual value
63of any atom.
64
65```jsx
66const doubledCountAtom = atom((get) => get(countAtom) * 2)
67
68function DoubleCounter() {
69 const [doubledCount] = useAtom(doubledCountAtom)
70 return <h2>{doubledCount}</h2>
71```
72
73## Recipes
74
75### Creating an atom from multiple atoms
76
77You can combine multiple atoms to create a derived atom.
78
79```jsx
80const count1 = atom(1)
81const count2 = atom(2)
82const count3 = atom(3)
83
84const sum = atom((get) => get(count1) + get(count2) + get(count3))
85```
86
87Or if you like fp patterns ...
88
89```jsx
90const atoms = [count1, count2, count3, ...otherAtoms]
91const sum = atom((get) => atoms.map(get).reduce((acc, count) => acc + count))
92```
93
94### Derived async atoms <img src="https://img.shields.io/badge/-needs_suspense-black" alt="needs suspense" />
95
96You can make the read function an async function too.
97
98```jsx
99const urlAtom = atom("https://json.host.com")
100const fetchUrlAtom = atom(
101 async (get) => {
102 const response = await fetch(get(urlAtom))
103 return await response.json()
104 }
105)
106
107function Status() {
108 // Re-renders the component after urlAtom changed and the async function above concludes
109 const [json] = useAtom(fetchUrlAtom)
110```
111
112### You can create a writable derived atom
113
114Specify a write function at the second argument. `get` will return the current
115value of an atom. `set` will update an atoms value.
116
117```jsx
118const decrementCountAtom = atom(
119 (get) => get(countAtom),
120 (get, set, _arg) => set(countAtom, get(countAtom) - 1),
121)
122
123function Counter() {
124 const [count, decrement] = useAtom(decrementCountAtom)
125 return (
126 <h1>
127 {count}
128 <button onClick={decrement}>Decrease</button>
129```
130
131### Write only atoms
132
133Just do not define a read function.
134
135```jsx
136const multiplyCountAtom = atom(null, (get, set, by) => set(countAtom, get(countAtom) * by))
137
138function Controls() {
139 const [, multiply] = useAtom(multiplyCountAtom)
140 return <button onClick={() => multiply(3)}>triple</button>
141```
142
143### Async actions
144
145Just make the write function an async function and call `set` when you're ready.
146
147```jsx
148const fetchCountAtom = atom(
149 (get) => get(countAtom),
150 async (_get, set, url) => {
151 const response = await fetch(url)
152 set(countAtom, (await response.json()).count)
153 }
154)
155
156function Controls() {
157 const [count, compute] = useAtom(fetchCountAtom)
158 return <button onClick={() => compute("http://count.host.com")}>compute</button>
159```
160
161## Installation notes
162
163This package requires some peer dependencies, which you need to install by
164yourself.
165
166```bash
167yarn add jotai react
168```
169
170## Learn Jotai
171
172[![free egghead Jotai introduction course by Daishi](./img/jotai-course-banner.jpg)](https://egghead.io/courses/manage-application-state-with-jotai-atoms-2c3a29f0?utm_source=github&utm_medium=cta&utm_term=jotai)
173
174## More documents
175
176- Basics
177 - [Concepts](./docs/basics/concepts.mdx)
178 - [Primitives](./docs/basics/primitives.mdx)
179 - [Async](./docs/basics/async.mdx)
180 - [Comparison](./docs/basics/comparison.mdx)
181 - [Showcase](./docs/basics/showcase.mdx)
182- Guides
183 - [TypeScript](./docs/guides/typescript.mdx)
184 - [Debugging](./docs/guides/debugging.mdx)
185 - [Testing](./docs/guides/testing.mdx)
186 - [Persistence](./docs/guides/persistence.mdx)
187 - [Next.js](./docs/guides/nextjs.mdx)
188 - [React Native](./docs/guides/react-native.mdx)
189 - [Resettable](./docs/guides/resettable.mdx)
190 - [No Suspense](./docs/guides/no-suspense.mdx)
191 - [Atoms in atom](./docs/guides/atoms-in-atom.mdx)
192- API
193 - [Core](./docs/api/core.mdx)
194 - [Utils](./docs/api/utils.mdx)
195 - [Devtools](./docs/api/devtools.mdx)
196 - [Babel](./docs/api/babel.mdx)
197- Integrations
198 - [Immer](./docs/integrations/immer.mdx)
199 - [Optics](./docs/integrations/optics.mdx)
200 - [Query](./docs/integrations/query.mdx)
201 - [XState](./docs/integrations/xstate.mdx)
202 - [Valtio](./docs/integrations/valtio.mdx)
203 - [Zustand](./docs/integrations/zustand.mdx)
204 - [Redux](./docs/integrations/redux.mdx)
205 - [URQL](./docs/integrations/urql.mdx)
206- Advanced Recipes
207 - [Large Objects](./docs/advanced-recipes/large-objects.mdx)
208 - [Atom Creators](./docs/advanced-recipes/atom-creators.mdx)