or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-atoms.mdindex.mdreact-integration.mdreact-utilities.mdvanilla-utilities.md
tile.json

react-integration.mddocs/

0

# React Integration

1

2

React hooks and components for integrating Jotai atoms with React applications. These provide the primary interface for using atoms in React components.

3

4

## Capabilities

5

6

### useAtom Hook

7

8

Primary hook for reading and writing atom values in React components.

9

10

```typescript { .api }

11

/**

12

* Hook for reading and writing writable atoms

13

* @param atom - The writable atom to use

14

* @param options - Optional configuration

15

* @returns Tuple of [value, setter] similar to useState

16

*/

17

function useAtom<Value, Args extends unknown[], Result>(

18

atom: WritableAtom<Value, Args, Result>,

19

options?: Options

20

): [Awaited<Value>, SetAtom<Args, Result>];

21

22

/**

23

* Hook for reading and writing primitive atoms

24

* @param atom - The primitive atom to use

25

* @param options - Optional configuration

26

* @returns Tuple of [value, setter] with standard setState interface

27

*/

28

function useAtom<Value>(

29

atom: PrimitiveAtom<Value>,

30

options?: Options

31

): [Awaited<Value>, SetAtom<[SetStateAction<Value>], void>];

32

33

/**

34

* Hook for read-only atoms (returns never for setter)

35

* @param atom - The read-only atom to use

36

* @param options - Optional configuration

37

* @returns Tuple of [value, never]

38

*/

39

function useAtom<Value>(

40

atom: Atom<Value>,

41

options?: Options

42

): [Awaited<Value>, never];

43

```

44

45

**Usage Examples:**

46

47

```typescript

48

import { atom, useAtom } from "jotai";

49

50

const countAtom = atom(0);

51

const textAtom = atom("hello");

52

53

function MyComponent() {

54

const [count, setCount] = useAtom(countAtom);

55

const [text, setText] = useAtom(textAtom);

56

57

return (

58

<div>

59

<p>Count: {count}</p>

60

<button onClick={() => setCount(count + 1)}>+</button>

61

<button onClick={() => setCount((prev) => prev - 1)}>-</button>

62

63

<input

64

value={text}

65

onChange={(e) => setText(e.target.value)}

66

/>

67

</div>

68

);

69

}

70

```

71

72

### useAtomValue Hook

73

74

Hook for reading atom values without the ability to write.

75

76

```typescript { .api }

77

/**

78

* Hook for reading atom values without write capability

79

* @param atom - The atom to read from

80

* @param options - Optional configuration

81

* @returns The current value of the atom

82

*/

83

function useAtomValue<Value>(

84

atom: Atom<Value>,

85

options?: Options

86

): Awaited<Value>;

87

```

88

89

**Usage Examples:**

90

91

```typescript

92

import { atom, useAtomValue } from "jotai";

93

94

const countAtom = atom(0);

95

const doubleCountAtom = atom((get) => get(countAtom) * 2);

96

97

function DisplayComponent() {

98

const count = useAtomValue(countAtom);

99

const doubleCount = useAtomValue(doubleCountAtom);

100

101

return (

102

<div>

103

<p>Count: {count}</p>

104

<p>Double: {doubleCount}</p>

105

</div>

106

);

107

}

108

```

109

110

### useSetAtom Hook

111

112

Hook for getting a setter function for writable atoms.

113

114

```typescript { .api }

115

/**

116

* Hook for getting a setter function for writable atoms

117

* @param atom - The writable atom to get setter for

118

* @param options - Optional configuration

119

* @returns Setter function for the atom

120

*/

121

function useSetAtom<Value, Args extends unknown[], Result>(

122

atom: WritableAtom<Value, Args, Result>,

123

options?: Options

124

): SetAtom<Args, Result>;

125

126

/**

127

* Hook for getting a setter function for primitive atoms

128

* @param atom - The primitive atom to get setter for

129

* @param options - Optional configuration

130

* @returns Standard setState-style setter function

131

*/

132

function useSetAtom<Value>(

133

atom: PrimitiveAtom<Value>,

134

options?: Options

135

): SetAtom<[SetStateAction<Value>], void>;

136

```

137

138

**Usage Examples:**

139

140

```typescript

141

import { atom, useSetAtom, useAtomValue } from "jotai";

142

143

const countAtom = atom(0);

144

const incrementAtom = atom(null, (get, set, amount: number) => {

145

set(countAtom, get(countAtom) + amount);

146

});

147

148

function Controls() {

149

const setCount = useSetAtom(countAtom);

150

const increment = useSetAtom(incrementAtom);

151

152

return (

153

<div>

154

<button onClick={() => setCount(0)}>Reset</button>

155

<button onClick={() => setCount((prev) => prev + 1)}>+1</button>

156

<button onClick={() => increment(5)}>+5</button>

157

</div>

158

);

159

}

160

161

function Display() {

162

const count = useAtomValue(countAtom);

163

return <p>Count: {count}</p>;

164

}

165

```

166

167

### Provider Component

168

169

React context provider for scoped atom stores.

170

171

```typescript { .api }

172

/**

173

* Provider component for scoped atom stores

174

* @param props - Component props

175

* @param props.children - React children

176

* @param props.store - Optional custom store, creates new one if not provided

177

* @returns ReactElement with store context

178

*/

179

function Provider(props: {

180

children?: ReactNode;

181

store?: Store;

182

}): ReactElement<

183

{ value: Store | undefined },

184

FunctionComponent<{ value: Store | undefined }>

185

>;

186

```

187

188

**Usage Examples:**

189

190

```typescript

191

import { Provider, createStore, atom, useAtom } from "jotai";

192

193

const countAtom = atom(0);

194

195

function App() {

196

return (

197

<Provider>

198

<Counter />

199

</Provider>

200

);

201

}

202

203

// With custom store

204

function AppWithCustomStore() {

205

const myStore = createStore();

206

207

return (

208

<Provider store={myStore}>

209

<Counter />

210

</Provider>

211

);

212

}

213

214

function Counter() {

215

const [count, setCount] = useAtom(countAtom);

216

return (

217

<div>

218

<p>{count}</p>

219

<button onClick={() => setCount((c) => c + 1)}>+</button>

220

</div>

221

);

222

}

223

```

224

225

### useStore Hook

226

227

Hook for accessing the current store context.

228

229

```typescript { .api }

230

/**

231

* Hook for accessing the current store context

232

* @param options - Optional configuration with custom store

233

* @returns The current store instance

234

*/

235

function useStore(options?: Options): Store;

236

237

interface Options {

238

store?: Store;

239

}

240

```

241

242

**Usage Examples:**

243

244

```typescript

245

import { useStore, atom } from "jotai";

246

247

const countAtom = atom(0);

248

249

function MyComponent() {

250

const store = useStore();

251

252

const handleDirectAccess = () => {

253

// Direct store access (not recommended for normal use)

254

const currentCount = store.get(countAtom);

255

store.set(countAtom, currentCount + 1);

256

};

257

258

return (

259

<button onClick={handleDirectAccess}>

260

Direct Store Access

261

</button>

262

);

263

}

264

265

// Using custom store

266

function MyComponentWithCustomStore() {

267

const customStore = createStore();

268

const store = useStore({ store: customStore });

269

270

// Store operations...

271

}

272

```

273

274

## Types and Interfaces

275

276

### Hook Options

277

278

Configuration options for hooks.

279

280

```typescript { .api }

281

interface Options {

282

/** Optional custom store to use instead of context store */

283

store?: Store;

284

}

285

```

286

287

### SetAtom Type

288

289

Type for atom setter functions returned by hooks.

290

291

```typescript { .api }

292

type SetAtom<Args extends unknown[], Result> = <A extends Args>(

293

...args: A

294

) => Result;

295

```

296

297

### React Types

298

299

React-specific types used by components and hooks.

300

301

```typescript { .api }

302

type ReactNode = React.ReactNode;

303

type ReactElement<P = any, T = any> = React.ReactElement<P, T>;

304

type FunctionComponent<P = {}> = React.FunctionComponent<P>;

305

```

306

307

## Advanced Usage Patterns

308

309

### Conditional Rendering with Suspense

310

311

```typescript

312

import { Suspense } from "react";

313

import { atom, useAtomValue } from "jotai";

314

315

const asyncDataAtom = atom(async () => {

316

const response = await fetch("/api/data");

317

return response.json();

318

});

319

320

function AsyncComponent() {

321

const data = useAtomValue(asyncDataAtom);

322

return <div>{JSON.stringify(data)}</div>;

323

}

324

325

function App() {

326

return (

327

<Suspense fallback={<div>Loading...</div>}>

328

<AsyncComponent />

329

</Suspense>

330

);

331

}

332

```

333

334

### Error Boundaries with Async Atoms

335

336

```typescript

337

import { ErrorBoundary } from "react-error-boundary";

338

import { atom, useAtomValue } from "jotai";

339

340

const errorAtom = atom(async () => {

341

throw new Error("Something went wrong");

342

});

343

344

function ErrorComponent() {

345

const data = useAtomValue(errorAtom);

346

return <div>{data}</div>;

347

}

348

349

function App() {

350

return (

351

<ErrorBoundary fallback={<div>Error occurred!</div>}>

352

<Suspense fallback={<div>Loading...</div>}>

353

<ErrorComponent />

354

</Suspense>

355

</ErrorBoundary>

356

);

357

}

358

```

359

360

### Multiple Stores

361

362

```typescript

363

import { Provider, createStore, atom, useAtom } from "jotai";

364

365

const userStore = createStore();

366

const appStore = createStore();

367

368

const userAtom = atom({ name: "Alice" });

369

const themeAtom = atom("light");

370

371

function App() {

372

return (

373

<Provider store={appStore}>

374

<ThemeProvider />

375

<Provider store={userStore}>

376

<UserProfile />

377

</Provider>

378

</Provider>

379

);

380

}

381

382

function ThemeProvider() {

383

const [theme, setTheme] = useAtom(themeAtom);

384

return (

385

<div className={`theme-${theme}`}>

386

<button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>

387

Toggle Theme

388

</button>

389

</div>

390

);

391

}

392

393

function UserProfile() {

394

const [user, setUser] = useAtom(userAtom);

395

return (

396

<div>

397

<p>User: {user.name}</p>

398

<button onClick={() => setUser({ name: "Bob" })}>

399

Change User

400

</button>

401

</div>

402

);

403

}

404

```