UNPKG

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