UNPKG

4.97 kBMarkdownView Raw
1<br>
2
3![Jotai (light mode)](./img/jotai-header-light.png#gh-light-mode-only)
4
5
6<br>
7
8visit [jotai.org](https://jotai.org) or `npm i jotai`
9
10[![Build Status](https://img.shields.io/github/actions/workflow/status/pmndrs/jotai/lint-and-type.yml?branch=main&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 scales from a simple useState replacement to an enterprise TypeScript application.
18
19- Minimal core API (2kb)
20- Many utilities and integrations
21- No string keys (compared to Recoil)
22
23Examples: [Demo 1](https://codesandbox.io/s/jotai-demo-47wvh) |
24[Demo 2](https://codesandbox.io/s/jotai-demo-forked-x2g5d)
25
26### First, create a primitive atom
27
28An atom represents a piece of state. All you need is to specify an initial
29value, which can be primitive values like strings and numbers, objects, and
30arrays. You can create as many primitive atoms as you want.
31
32```jsx
33import { atom } from 'jotai'
34
35const countAtom = atom(0)
36const countryAtom = atom('Japan')
37const citiesAtom = atom(['Tokyo', 'Kyoto', 'Osaka'])
38const mangaAtom = atom({ 'Dragon Ball': 1984, 'One Piece': 1997, Naruto: 1999 })
39```
40
41### Use the atom in your components
42
43It can be used like `React.useState`:
44
45```jsx
46import { useAtom } from 'jotai'
47
48function Counter() {
49 const [count, setCount] = useAtom(countAtom)
50 return (
51 <h1>
52 {count}
53 <button onClick={() => setCount((c) => c + 1)}>one up</button>
54 ...
55```
56
57### Create derived atoms with computed values
58
59A new read-only atom can be created from existing atoms by passing a read
60function as the first argument. `get` allows you to fetch the contextual value
61of any atom.
62
63```jsx
64const doubledCountAtom = atom((get) => get(countAtom) * 2)
65
66function DoubleCounter() {
67 const [doubledCount] = useAtom(doubledCountAtom)
68 return <h2>{doubledCount}</h2>
69}
70```
71
72### Creating an atom from multiple atoms
73
74You can combine multiple atoms to create a derived atom.
75
76```jsx
77const count1 = atom(1)
78const count2 = atom(2)
79const count3 = atom(3)
80
81const sum = atom((get) => get(count1) + get(count2) + get(count3))
82```
83
84Or if you like fp patterns ...
85
86```jsx
87const atoms = [count1, count2, count3, ...otherAtoms]
88const sum = atom((get) => atoms.map(get).reduce((acc, count) => acc + count))
89```
90
91### Derived async atoms <img src="https://img.shields.io/badge/-needs_suspense-black" alt="needs suspense" />
92
93You can make the read function an async function too.
94
95```jsx
96const urlAtom = atom('https://json.host.com')
97const fetchUrlAtom = atom(async (get) => {
98 const response = await fetch(get(urlAtom))
99 return await response.json()
100})
101
102function Status() {
103 // Re-renders the component after urlAtom is changed and the async function above concludes
104 const [json] = useAtom(fetchUrlAtom)
105 ...
106```
107
108### You can create a writable derived atom
109
110Specify a write function at the second argument. `get` will return the current
111value of an atom. `set` will update the value of an atom.
112
113```jsx
114const decrementCountAtom = atom(
115 (get) => get(countAtom),
116 (get, set, _arg) => set(countAtom, get(countAtom) - 1)
117)
118
119function Counter() {
120 const [count, decrement] = useAtom(decrementCountAtom)
121 return (
122 <h1>
123 {count}
124 <button onClick={decrement}>Decrease</button>
125 ...
126```
127
128### Write only derived atoms
129
130Just do not define a read function.
131
132```jsx
133const multiplyCountAtom = atom(null, (get, set, by) =>
134 set(countAtom, get(countAtom) * by)
135)
136
137function Controls() {
138 const [, multiply] = useAtom(multiplyCountAtom)
139 return <button onClick={() => multiply(3)}>triple</button>
140}
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 (
159 <button onClick={() => compute('http://count.host.com')}>compute</button>
160 ...
161```
162
163## Links
164
165- [website](https://jotai.org)
166- [documentation](https://jotai.org/docs)
167- [course](https://egghead.io/courses/manage-application-state-with-jotai-atoms-2c3a29f0)