### Install jotai-urql
Source: https://jotai.org/docs/extensions/urql
Install the necessary packages for the jotai-urql extension.
```bash
npm install jotai-urql @urql/core wonka
```
--------------------------------
### Install xstate and jotai-xstate
Source: https://jotai.org/docs/extensions/xstate
Install the necessary packages for XState integration with Jotai.
```bash
npm install xstate jotai-xstate
```
--------------------------------
### Install jotai-cache
Source: https://jotai.org/docs/extensions/cache
Install the jotai-cache library using npm.
```bash
npm install jotai-cache
```
--------------------------------
### Install jotai-scope
Source: https://jotai.org/docs/extensions/scope
Install the jotai-scope package using npm.
```bash
npm install jotai-scope
```
--------------------------------
### Install Valtio and jotai-valtio
Source: https://jotai.org/docs/extensions/valtio
Install the necessary packages to use Valtio integration with Jotai.
```bash
npm install valtio jotai-valtio
```
--------------------------------
### Install Dependencies
Source: https://jotai.org/docs/extensions/valtio
Install Jotai, Valtio, and the Jotai-Valtio integration package. These are essential for using both state management libraries together.
```bash
npm install jotai valtio jotai-valtio
```
--------------------------------
### Install jotai-history
Source: https://jotai.org/docs/third-party/history
Install the jotai-history package using npm.
```bash
npm install jotai-history
```
--------------------------------
### Install Optics Packages
Source: https://jotai.org/docs/extensions/optics
Install the necessary packages for using Jotai optics.
```bash
npm install optics-ts jotai-optics
```
--------------------------------
### Integrate React Query Devtools with Jotai
Source: https://jotai.org/docs/extensions/query
This example demonstrates how to install and integrate the React Query Devtools into your Jotai application. Ensure the Devtools are placed within the `QueryClientProvider` to function correctly.
```bash
npm install @tanstack/react-query-devtools
```
```javascript
import {
QueryClientProvider,
QueryClient,
QueryCache,
} from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import { queryClientAtom } from 'jotai-tanstack-query'
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: Infinity,
},
},
})
const HydrateAtoms = ({ children }) => {
useHydrateAtoms([[queryClientAtom, queryClient]])
return children
}
export const App = () => {
return (
)
}
```
--------------------------------
### Install jotai-relay and relay-runtime
Source: https://jotai.org/docs/extensions/relay
Install the necessary packages for Jotai-Relay integration using npm.
```bash
npm install jotai-relay relay-runtime
```
--------------------------------
### Install jotai-effect
Source: https://jotai.org/docs/extensions/effect
Install the jotai-effect package using npm.
```bash
npm install jotai-effect
```
--------------------------------
### Install Redux and Jotai-Redux
Source: https://jotai.org/docs/extensions/redux
Install the necessary packages for Redux integration with Jotai.
```bash
npm install redux jotai-redux
```
--------------------------------
### Conditional Dependency with Multiple Conditions using `soonAll`
Source: https://jotai.org/docs/third-party/eager
Combines `soon` and `soonAll` to handle multiple conditional dependencies. This example shows how to conditionally get a `queryAtom` based on both `isAdminAtom` and `enabledAtom`.
```javascript
import { soon, soonAll } from 'jotai-eager'
// Given the following definitions:
// const queryAtom: Atom>;
// const isAdminAtom: Atom>;
// const enabledAtom: Atom>;
// Atom>
const restrictedItemAtom = atom((get) => {
return soon(
soonAll(get(isAdminAtom), get(enabledAtom)),
([isAdmin, enabled]) => (isAdmin && enabled ? get(queryAtom) : null),
)
})
```
--------------------------------
### Install jotai-location
Source: https://jotai.org/docs/extensions/location
Install the jotai-location package using npm.
```bash
npm install jotai-location
```
--------------------------------
### Install Zustand and Jotai-Zustand
Source: https://jotai.org/docs/extensions/zustand
Install the necessary packages for integrating Zustand with Jotai.
```bash
npm install zustand jotai-zustand
```
--------------------------------
### Create Next.js App with Jotai Example
Source: https://jotai.org/docs/guides/nextjs
Quickly set up a new Next.js project with Jotai integration using the provided `create-next-app` command.
```bash
npx create-next-app --example with-jotai with-jotai-app
```
--------------------------------
### Install jotai-tanstack-query
Source: https://jotai.org/docs/extensions/query
Install the necessary packages for using jotai-tanstack-query. This includes the extension library and the core TanStack Query package.
```bash
npm install jotai-tanstack-query @tanstack/query-core
```
--------------------------------
### Install @swc-jotai/react-refresh
Source: https://jotai.org/docs/tools/swc
Install the React Refresh plugin for Jotai using npm.
```bash
npm install --save-dev @swc-jotai/react-refresh
```
--------------------------------
### Basic Jotai Setup
Source: https://jotai.org/docs/utilities/family
This snippet shows the fundamental setup for a Jotai application within a React project. It includes necessary imports and the root component rendering.
```tsx
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App.tsx';
createRoot(document.getElementById('root')!).render(
);
```
--------------------------------
### Install jotai-trpc
Source: https://jotai.org/docs/extensions/trpc
Install the necessary packages for using Jotai with tRPC.
```bash
npm install jotai-trpc @trpc/client @trpc/server
```
--------------------------------
### Basic Valtio Store Setup
Source: https://jotai.org/docs/extensions/valtio
Define a simple Valtio store with some initial state. This store will be used and managed by Jotai.
```typescript
import { proxy } from 'valtio';
const state = proxy({
count: 0,
text: 'hello',
});
export default state;
```
--------------------------------
### Install Immer and Jotai Immer
Source: https://jotai.org/docs/extensions/immer
Install the necessary packages for using Immer with Jotai. This is a prerequisite for using `atomWithImmer`.
```bash
npm install immer jotai-immer
```
--------------------------------
### Install jotai-eager
Source: https://jotai.org/docs/third-party/eager
Installs the jotai-eager package using npm. This is a prerequisite for using eager atoms.
```bash
npm install jotai-eager
```
--------------------------------
### Install @swc-jotai/debug-label
Source: https://jotai.org/docs/tools/swc
Install the debug label plugin for Jotai using npm.
```bash
npm install --save-dev @swc-jotai/debug-label
```
--------------------------------
### Expensive Initialization Example
Source: https://jotai.org/docs/utilities/lazy
This example shows a primitive atom with an initial value that must be computed at definition time, even if it's only used in a specific part of the application.
```javascript
const imageDataAtom = atom(initializeExpensiveImage()) // 1) has to be computed here
function Home() {
...
}
function ImageEditor() {
// 2) used only in this route
const [imageData, setImageData] = useAtom(imageDataAtom);
...
}
function App() {
return (
)
}
```
--------------------------------
### Atom Creation Examples
Source: https://jotai.org/docs/core/atom
Provides examples of how to use the `atom` function to create different types of atoms: primitive, read-only derived, read-write derived, and write-only derived.
```javascript
const primitiveAtom = atom(initialValue)
const derivedAtomWithRead = atom(read)
const derivedAtomWithReadWrite = atom(read, write)
const derivedAtomWithWriteOnly = atom(null, write)
```
--------------------------------
### Install jotai-rolldown Plugin
Source: https://jotai.org/docs/tools/rolldown
Install the jotai-rolldown plugin as a development dependency using npm.
```bash
npm install --save-dev jotai-rolldown
```
--------------------------------
### Zustand Store Subscription Example
Source: https://jotai.org/docs/extensions/zustand
Demonstrates creating a Jotai atom from a Zustand store and logging store state changes to the console.
```typescript
import { useAtom } from 'jotai';
import { atomWithStore } from 'jotai/zustand';
import create from 'zustand/vanilla';
const store = create(() => ({ count: 0 }));
store.subscribe(() => {
console.log('new count', store.getState().count);
});
const stateAtom = atomWithStore(store);
const Counter = () => {
const [state, setState] = useAtom(stateAtom);
return (
<>
count: {state.count}
>
);
};
export default function App() {
return (
Hello CodeSandbox
);
}
```
--------------------------------
### Jotai Optics Example with Controls
Source: https://jotai.org/docs/extensions/optics
An example demonstrating how to use `focusAtom` to manage individual properties of an object atom and update them via UI controls.
```typescript
import { atom } from 'jotai'
import { focusAtom } from 'jotai-optics'
const objectAtom = atom({ a: 5, b: 10 })
const aAtom = focusAtom(objectAtom, (optic) => optic.prop('a'))
const bAtom = focusAtom(objectAtom, (optic) => optic.prop('b'))
const Controls = () => {
const [a, setA] = useAtom(aAtom)
const [b, setB] = useAtom(bAtom)
return (
Value of a: {a}Value of b: {b}
)
}
```
--------------------------------
### Install Bunja
Source: https://jotai.org/docs/third-party/bunja
Install Bunja using npm. This command adds the Bunja library to your project dependencies.
```bash
npm install bunja
```
--------------------------------
### Usage Example of atomWithToggleAndStorage
Source: https://jotai.org/docs/recipes/atom-with-toggle-and-storage
This example shows how to create and use an atomWithToggleAndStorage instance. The state will be initialized to false and stored in localStorage.
```typescript
import { atomWithToggleAndStorage } from 'XXX'
// will have an initial value set to false & get stored in localStorage under the key "isActive"
const isActiveAtom = atomWithToggleAndStorage('isActive')
```
--------------------------------
### Counter Example with Simplified Jotai Atom
Source: https://jotai.org/docs/guides/core-internals
Demonstrates how to use the simplified atom implementation to create a counter component. This example showcases the basic usage of the `useAtom` hook for reading and updating state.
```javascript
Here's an example using our simplified atom implementation. Counter example
Ref tweet: Demystifying the internal of jotai
```
--------------------------------
### atomWithInfiniteQuery Usage Example
Source: https://jotai.org/docs/extensions/query
Demonstrates using atomWithInfiniteQuery to fetch paginated posts. Includes configuration for fetching next pages and initial parameters.
```javascript
import { atom, useAtom } from 'jotai'
import { atomWithInfiniteQuery } from 'jotai-tanstack-query'
const postsAtom = atomWithInfiniteQuery(() => ({
queryKey: ['posts'],
queryFn: async ({ pageParam }) => {
const res = await fetch(`https://jsonplaceholder.typicode.com/posts?_page=${pageParam}`)
return res.json()
},
getNextPageParam: (lastPage, allPages, lastPageParam) => lastPageParam + 1,
initialPageParam: 1,
}))
const Posts = () => {
const [{ data, fetchNextPage, isPending, isError, isFetching }] =
useAtom(postsAtom)
if (isPending) return
Loading...
if (isError) return
Error
return (
<>
{data.pages.map((page, index) => (
{page.map((post: any) => (
{post.title}
))}
))}
>
)
}
```
--------------------------------
### useAtomCallback Example
Source: https://jotai.org/docs/utilities/callback
An example demonstrating how to use useAtomCallback to imperatively read an atom's value and update local state. The callback must be stable and wrapped with useCallback.
```javascript
import { useEffect, useState, useCallback } from 'react'
import { Provider, atom, useAtom } from 'jotai'
import { useAtomCallback } from 'jotai/utils'
const countAtom = atom(0)
const Counter = () => {
const [count, setCount] = useAtom(countAtom)
return (
<>
{count}
>
)
}
const Monitor = () => {
const [count, setCount] = useState(0)
const readCount = useAtomCallback(
useCallback((get) => {
const currCount = get(countAtom)
setCount(currCount)
return currCount
}, []),
)
useEffect(() => {
const timer = setInterval(async () => {
console.log(readCount())
}, 1000)
return () => {
clearInterval(timer)
}
}, [readCount])
return
current count: {count}
}
```
--------------------------------
### Install bunshi for Scoped Atoms
Source: https://jotai.org/docs/extensions/scope
Install the bunshi library, formerly jotai-molecules, to enable defining atoms within a component tree that can depend on props and component state.
```bash
npm install bunshi
```
--------------------------------
### Async Write Atom Example
Source: https://jotai.org/docs/guides/async
An example of an async write atom. The `write` function can perform asynchronous operations before updating state.
```javascript
const asyncAtom = atom(async (get) => ...)
const writeAtom = atom(null, async (get, set, payload) => {
await get(asyncAtom)
// ...
})
```
--------------------------------
### Jotai splitAtom Example
Source: https://jotai.org/docs/utilities/split
This example demonstrates how to use splitAtom to manage a list of todo items. Each todo item is an atom, allowing for independent updates and management.
```typescript
import { Provider, atom, useAtom, PrimitiveAtom } from 'jotai';
import { splitAtom } from 'jotai/utils';
import './styles.css';
const initialState = [
{
task: 'help the town',
done: false,
},
{
task: 'feed the dragon',
done: false,
},
];
const todosAtom = atom(initialState);
const todoAtomsAtom = splitAtom(todosAtom);
type TodoType = (typeof initialState)[number];
const TodoItem = ({ todoAtom, remove, }: {
todoAtom: PrimitiveAtom;
remove: () => void;
}) => {
const [todo, setTodo] = useAtom(todoAtom);
return (
);
};
const App = () => (
);
export default App;
```
--------------------------------
### App.tsx Integration Example
Source: https://jotai.org/docs/extensions/valtio
Integrate the Counter component into your main App component. This shows a complete example of how the Valtio state is managed and displayed via Jotai.
```typescript
import React from 'react';
import Counter from './Counter';
function App() {
return (
Jotai + Valtio Example
);
}
export default App;
```
--------------------------------
### Jotai splitAtom Todo List Example
Source: https://jotai.org/docs/utilities/split
This example demonstrates how to use splitAtom to manage a list of todo items. Each todo item is an individual atom, allowing for independent updates, and the list itself is also an atom managed by splitAtom.
```javascript
import { Provider, atom, useAtom, PrimitiveAtom } from 'jotai'
import { splitAtom } from 'jotai/utils'
import './styles.css'
const initialState = [
{
task: 'help the town',
done: false,
},
{
task: 'feed the dragon',
done: false,
},
]
const todosAtom = atom(initialState)
const todoAtomsAtom = splitAtom(todosAtom)
type TodoType = (typeof initialState)[number]
const TodoItem = ({
todoAtom,
remove,
}: {
todoAtom: PrimitiveAtom
remove: () => void
}) => {
const [todo, setTodo] = useAtom(todoAtom)
return (
)
}
const App = () => (
)
export default App
```
--------------------------------
### Basic atomWithReducer Example
Source: https://jotai.org/docs/utilities/reducer
Demonstrates creating an atom that manages a count state using a reducer function. This is useful for complex state transitions.
```typescript
import { atomWithReducer } from 'jotai/utils'
const countReducer = (prev, action) => {
if (action.type === 'inc') return prev + 1
if (action.type === 'dec') return prev - 1
throw new Error('unknown action type')
}
const countReducerAtom = atomWithReducer(0, countReducer)
```
--------------------------------
### SessionStorage Persistence with atomWithStorage
Source: https://jotai.org/docs/guides/persistence
Example of using `atomWithStorage` with a custom `sessionStorage` implementation. Requires importing `createJSONStorage`.
```javascript
import { atomWithStorage, createJSONStorage } from 'jotai/utils'
const storage = createJSONStorage(() =>
typeof window !== 'undefined' ? window.sessionStorage : undefined,
)
const someAtom = atomWithStorage('some-key', someInitialValue, storage)
```
--------------------------------
### Basic Location Atom Setup
Source: https://jotai.org/docs/extensions/location
Initialize an atom with the `atomWithLocation` function to manage the current URL location. This atom can then be used with Jotai's `useAtom` hook.
```typescript
import { useAtom } from 'jotai';
import { atomWithLocation } from 'jotai-location';
const locationAtom = atomWithLocation();
```
--------------------------------
### Initialize Jotai URQL Client and Provider
Source: https://jotai.org/docs/extensions/urql
Demonstrates how to create a URQL client, initialize the `clientAtom` with it, and wrap the application with both Jotai's `Provider` and URQL's `Provider` to ensure the same client instance is used throughout.
```javascript
import { Suspense } from 'react'
import { Provider } from 'jotai/react'
import { useHydrateAtoms } from 'jotai/react/utils'
import { clientAtom } from 'jotai-urql'
import {
createClient,
cacheExchange,
fetchExchange,
Provider as UrqlProvider,
} from 'urql'
const urqlClient = createClient({
url: 'https://countries.trevorblades.com/',
exchanges: [cacheExchange, fetchExchange],
fetchOptions: () => {
return { headers: {} }
},
})
const HydrateAtoms = ({ children }) => {
useHydrateAtoms([[clientAtom, urqlClient]])
return children
}
export default function MyApp({ Component, pageProps }) {
return (
)
}
```
--------------------------------
### Creating a Custom JSON Storage
Source: https://jotai.org/docs/utilities/storage
This example shows how to create a custom storage object using createJSONStorage, allowing for custom JSON reviver and replacer options.
```javascript
const storage = createJSONStorage(
//getStringStorage
() => window.localStorage, // or window.sessionStorage, asyncStorage or alike
// options (optional)
{
reviver,
replacer,
},
)
```
--------------------------------
### Conditional Dependency with `soon`
Source: https://jotai.org/docs/third-party/eager
Uses the `soon` function for conditional dependencies, allowing sync/async transformations on data eagerly. This example demonstrates how to conditionally get a `queryAtom` based on the value of an `isAdminAtom`.
```javascript
import { soon } from 'jotai-eager'
// Given the following definitions:
// const queryAtom: Atom>;
// const isAdminAtom: Atom>;
// Atom>
const restrictedItemAtom = atom((get) => {
const isAdmin = get(isAdminAtom)
return soon(isAdmin, (isAdmin) => (isAdmin ? get(queryAtom) : null))
})
```
--------------------------------
### React Component with Jotai Effect for Interval Updates
Source: https://jotai.org/docs/extensions/effect
This example demonstrates a React component that uses Jotai Effect to manage an interval for incrementing a counter. The effect is conditionally started and cleared based on a play/pause atom.
```typescript
import { Provider, useAtom } from 'jotai/react'
import { atom, createStore } from 'jotai/vanilla'
import { atomWithReset, RESET } from 'jotai/utils'
import { observe } from 'jotai-effect'
const playPauseAtom = atom(false)
const countAtom = atomWithReset(0)
const store = createStore()
// Effect to manage interval for count updates
observe((get, set) => {
if (get(playPauseAtom)) {
const intervalId = setInterval(() => {
set(countAtom, (prev) => prev + 1)
}, 500)
return () => clearInterval(intervalId)
}
}, store)
function Component() {
const [shouldPlay, setPlayPause] = useAtom(playPauseAtom)
const [count, setCount] = useAtom(countAtom)
const resetCount = () => setCount(RESET)
const togglePlayPause = () => setPlayPause((prev) => !prev)
return (
Count: {count}
)
}
export default function App() {
return (
)
}
```
--------------------------------
### Basic Demo: Fetching Pokemons with Jotai and URQL
Source: https://jotai.org/docs/extensions/urql
This basic demo demonstrates how to set up a URQL client and use Jotai atoms to fetch a list of pokemons. The fetched data is then logged to the console.
```typescript
import { Suspense } from 'react'; import { useAtom } from 'jotai'; import { atomsWithQuery } from 'jotai-urql'; import { createClient, gql } from '@urql/core'; import './index.css'; const client = createClient({ url: 'https://trygql.formidable.dev/graphql/basic-pokedex', }); const POKEMONS_QUERY = gql` query Pokemons {
pokemons(limit: 10) {
id
name
}
}
`; const [queryAtom] = atomsWithQuery( POKEMONS_QUERY, () => ({}), undefined, () => client ); const Main = () => { const [data] = useAtom(queryAtom); console.log('data', data); return (
```
--------------------------------
### Create and Use a Custom Store
Source: https://jotai.org/docs/core/store
Demonstrates creating a custom store, setting an atom's value, and subscribing to changes. Use this when you need a dedicated store instance, for example, when passing it to a Provider.
```javascript
const myStore = createStore()
const countAtom = atom(0)
myStore.set(countAtom, 1)
const unsub = myStore.sub(countAtom, () => {
console.log('countAtom value is changed to', myStore.get(countAtom))
})
// unsub() to unsubscribe
const Root = () => (
)
```
--------------------------------
### Basic Valtio Store Setup
Source: https://jotai.org/docs/extensions/valtio
Define a simple Valtio store. This store will hold your application's state and can be accessed and modified using Valtio's proxy capabilities.
```typescript
import { proxy } from 'valtio';
const state = proxy({
count: 0,
});
export default state;
```
--------------------------------
### Create and Use atomWithLocation
Source: https://jotai.org/docs/extensions/location
Demonstrates creating an atom with `atomWithLocation` and using it with `useAtom` to control navigation and display active states based on the current location. This example shows how to link buttons to specific paths and query parameters.
```javascript
import { useAtom } from 'jotai'
import { atomWithLocation } from 'jotai-location'
const locationAtom = atomWithLocation()
const App = () => {
const [loc, setLoc] = useAtom(locationAtom)
return (
)
}
```
--------------------------------
### Main Application Entry Point
Source: https://jotai.org/docs/extensions/location
The `main.tsx` file sets up the React application within `StrictMode` and renders the `App` component.
```typescript
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App.tsx';
import './index.css';
createRoot(document.getElementById('root')!).render(
,
);
```
--------------------------------
### atomWithQuery Usage Example
Source: https://jotai.org/docs/extensions/query
Shows how to create and use an atom with atomWithQuery to fetch user data based on an ID atom. Includes loading and error state handling.
```javascript
import { atom, useAtom } from 'jotai'
import { atomWithQuery } from 'jotai-tanstack-query'
const idAtom = atom(1)
const userAtom = atomWithQuery((get) => ({
queryKey: ['users', get(idAtom)],
queryFn: async ({ queryKey: [, id] }) => {
const res = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`)
return res.json()
},
}))
const UserData = () => {
const [{ data, isPending, isError }] = useAtom(userAtom)
if (isPending) return
Loading...
if (isError) return
Error
return
{JSON.stringify(data)}
}
```
--------------------------------
### Example: Resetting Todo List with useResetAtom
Source: https://jotai.org/docs/utilities/resettable
Example of using the useResetAtom hook to create a button that resets the todoListAtom to its initial state.
```typescript
import { useResetAtom } from 'jotai/utils'
import { todoListAtom } from './store'
const TodoResetButton = () => {
const resetTodoList = useResetAtom(todoListAtom)
return
}
```
--------------------------------
### Generic atomWithSomething Signature
Source: https://jotai.org/docs/extensions/query
Illustrates the general signature for Jotai TanStack Query atoms. It takes a function to get options and an optional function to get the QueryClient.
```javascript
const dataAtom = atomWithSomething(getOptions, getQueryClient)
```
--------------------------------
### Initiate multiple async dependencies simultaneously with get.all()
Source: https://jotai.org/docs/third-party/eager
Uses the `get.all()` API within an `eagerAtom` to initiate multiple asynchronous dependencies concurrently. This avoids request waterfalls and improves efficiency when fetching related data.
```tsx
const myMessages = eagerAtom((get) => {
const [user, messages] = get.all([userAtom, messagesAtom])
return messages.filter((msg) => msg.authorId === user.id)
}) // => Atom>
```
--------------------------------
### Initialize Jotai Provider with TanStack Query Client
Source: https://jotai.org/docs/extensions/query
This snippet shows how to initialize the Jotai Provider and use `useHydrateAtoms` to set up the TanStack Query client. This is crucial for ensuring that `atomWithQuery` and other parts of the app reference the same `QueryClient` instance, preventing stale data issues.
```javascript
import { Provider } from 'jotai/react'
import { useHydrateAtoms } from 'jotai/react/utils'
import {
useMutation,
useQueryClient,
QueryClient,
QueryClientProvider,
} from '@tanstack/react-query'
import { atomWithQuery, queryClientAtom } from 'jotai-tanstack-query'
const queryClient = new QueryClient()
const HydrateAtoms = ({ children }) => {
useHydrateAtoms([[queryClientAtom, queryClient]])
return children
}
export const App = () => {
return (
{/*
This Provider initialisation step is needed so that we reference the same
queryClient in both atomWithQuery and other parts of the app. Without this,
our useQueryClient() hook will return a different QueryClient object
*/}
)
}
export const todosAtom = atomWithQuery((get) => {
return {
queryKey: ['todos'],
queryFn: () => fetch('/todos'),
}
})
export const useTodoMutation = () => {
const queryClient = useQueryClient()
return useMutation(
async (body: todo) => {
await fetch('/todo', { Method: 'POST', Body: body })
},
{
onSuccess: () => {
void queryClient.invalidateQueries(['todos'])
},
onError,
}
)
}
```
--------------------------------
### Example Usage of useAtomEffect for Channel Subscriptions
Source: https://jotai.org/docs/recipes/use-atom-effect
This example demonstrates how to use useAtomEffect to subscribe to a channel and update messages. It utilizes atomFamily for managing channel subscriptions and stable callbacks for the effect function.
```typescript
import { useCallbackOne as useStableCallback } from 'use-memo-one'
import { atom, useAtom } from 'jotai'
import { atomFamily } from 'jotai/utils'
import { useAtomEffect } from './useAtomEffect'
const channelSubscriptionAtomFamily = atomFamily(
(channelId: string) => {
return atom(new Channel(channelId))
},
)
const messagesAtom = atom([])
function Messages({ channelId }: { channelId: string }) {
const [messages] = useAtom(messagesAtom)
useAtomEffect(
useStableCallback(
(get, set) => {
const channel = get(channelSubscriptionAtomFamily(channelId))
const unsubscribe = channel.subscribe((message) => {
set(messagesAtom, (prev) => [...prev, message])
})
return unsubscribe
},
[channelId],
),
)
return (
<>
You have {messages.length} messages
{messages.map((message) => (
{message.text}
))}
>
)
}
```
--------------------------------
### createStore
Source: https://jotai.org/docs/core/store
Creates a new, empty store instance. This store can be passed to the `Provider` component or used directly to manage atom states. It provides methods for getting atom values (`get`), setting atom values (`set`), and subscribing to atom changes (`sub`).
```APIDOC
## createStore
### Description
Creates a new, empty store instance. This store can be passed to the `Provider` component or used directly to manage atom states. It provides methods for getting atom values (`get`), setting atom values (`set`), and subscribing to atom changes (`sub`).
### Usage
```javascript
const myStore = createStore()
const countAtom = atom(0)
myStore.set(countAtom, 1)
const unsub = myStore.sub(countAtom, () => {
console.log('countAtom value is changed to', myStore.get(countAtom))
})
// unsub() to unsubscribe
```
### Provider Integration
```javascript
const Root = () => (
)
```
```
--------------------------------
### Jotai and Urql Dependencies
Source: https://jotai.org/docs/extensions/urql
These are the necessary dependencies for integrating Jotai with Urql. Ensure these are installed in your project.
```json
{ "name": "vite-react-typescript-starter", "private": true, "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", "build": "tsc -b && vite build", "lint": "eslint .", "preview": "vite preview" }, "dependencies": { "@urql/core": "3.1.1", "graphql": "15.5.0", "jotai": "^2.10.1", "react": "^18.3.1", "react-dom": "^18.3.1", "jotai-urql": "0.3.1" }, "devDependencies": { "@eslint/js": "^9.12.0", "@types/react": "^18.3.11", "@types/react-dom": "^18.3.1", "@vitejs/plugin-react": "^4.3.2", "eslint": "^9.12.0", "eslint-plugin-react-hooks": "^5.0.0", "eslint-plugin-react-refresh": "^0.4.12", "globals": "^15.11.0", "typescript": "^5.6.2", "typescript-eslint": "^8.10.0", "vite": "^5.4.9" } }
```
--------------------------------
### Using atomWithQuery with Relay
Source: https://jotai.org/docs/extensions/relay
Demonstrates how to create a Jotai atom using `atomWithQuery` to fetch data with Relay. This includes setting up the Relay environment and defining the query.
```javascript
import React, { Suspense } from 'react'
import { Provider, useAtom } from 'jotai'
import { useHydrateAtoms } from 'jotai/utils'
import { environmentAtom, atomWithQuery } from 'jotai-relay'
import { Environment, Network, RecordSource, Store } from 'relay-runtime'
import graphql from 'babel-plugin-relay/macro'
const myEnvironment = new Environment({
network: Network.create(async (params, variables) => {
const response = await fetch('https://countries.trevorblades.com/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: params.text,
variables,
}),
})
return response.json()
}),
store: new Store(new RecordSource()),
})
const countriesAtom = atomWithQuery(
graphql`
query AppCountriesQuery {
countries {
name
}
}
`,
() => ({}),
)
const Main = () => {
const [data] = useAtom(countriesAtom)
return (
{data.countries.map(({ name }) => (
{name}
))}
)
}
const HydrateAtoms = ({ children }) => {
useHydrateAtoms([[environmentAtom, myEnvironment]])
return children
}
const App = () => {
return (
)
}
```
--------------------------------
### Add debugLabel to atom
Source: https://jotai.org/docs/tools/babel
Example of how the jotai-babel/plugin-debug-label transforms a simple atom declaration by adding a debugLabel.
```javascript
export const countAtom = atom(0)
```
```javascript
export const countAtom = atom(0)
countAtom.debugLabel = 'countAtom'
```
--------------------------------
### Add debugLabel to default export atom
Source: https://jotai.org/docs/tools/babel
Example of how the jotai-babel/plugin-debug-label handles default exports by inferring the debugLabel from the filename.
```javascript
// countAtom.ts
export default atom(0)
```
```javascript
// countAtom.ts
const countAtom = atom(0)
countAtom.debugLabel = 'countAtom'
export default countAtom
```
--------------------------------
### Create tRPC Client with Jotai
Source: https://jotai.org/docs/extensions/trpc
Demonstrates creating a tRPC client instance using `createTRPCJotai` and configuring it with HTTP links. This setup is required before defining tRPC-related atoms.
```typescript
import { createTRPCJotai } from 'jotai-trpc'
const trpc = createTRPCJotai({
links: [
httpLink({
url: myUrl,
}),
],
})
const idAtom = atom('foo')
const queryAtom = trpc.bar.baz.atomWithQuery((get) => get(idAtom))
```
--------------------------------
### Using splitAtom with unwrap
Source: https://jotai.org/docs/guides/migrating-to-v2-api
Example of using `splitAtom` with `unwrap` to handle async data. Note that `unwrap` is unstable.
```javascript
const splittedAtom = splitAtom(unwrap(asyncArrayAtom, () => []))
```
--------------------------------
### Basic usage of useAtom
Source: https://jotai.org/docs/core/use-atom
Demonstrates how to use the useAtom hook to get the value of an atom and its corresponding update function.
```APIDOC
## Basic usage of useAtom
```javascript
const [value, setValue] = useAtom(anAtom)
```
The `setValue` function takes a single argument, which is passed to the atom's write function. If no write function is explicitly defined for the atom, `setValue` will directly set the atom's value to the argument provided.
```
--------------------------------
### Define Initial Values for Resettable Atoms
Source: https://jotai.org/docs/utilities/resettable
Example of defining resettable atoms for a number and a list of todos using atomWithReset.
```typescript
import { atomWithReset } from 'jotai/utils'
const dollarsAtom = atomWithReset(0)
const todoListAtom = atomWithReset([
{ description: 'Add a todo', checked: false },
])
```
--------------------------------
### Using atomWithListeners in a Component
Source: https://jotai.org/docs/recipes/atom-with-listeners
Example of how to use the atomWithListeners hook within a React component to listen for state changes in an atom.
```typescript
import { useCallback } from 'react'
import { useAtom, useSetAtom } from 'jotai'
import { atomWithListeners } from './atomWithListeners'
const [countAtom, useCountListener] = atomWithListeners(0)
function EvenCounter() {
const [evenCount, setEvenCount] = useAtom(countAtom)
useCountListener(
useCallback(
(get, set, newVal, prevVal) => {
// Every time `countAtom`'s value is set, we check if its new value
// is even, and if it is, we increment `evenCount`.
if (newVal % 2 === 0) {
setEvenCount((c) => c + 1)
}
},
[setEvenCount],
),
)
return <>Count was set to an even number {evenCount} times.>
}
```
--------------------------------
### Creating and Interacting with a Store
Source: https://jotai.org/docs/guides/migrating-to-v2-api
Demonstrates how to create a store, set and get atom values, and subscribe to atom changes. Use this for direct state manipulation outside of React components.
```javascript
import { createStore } from 'jotai'
const store = createStore()
store.set(fooAtom, 'foo')
console.log(store.get(fooAtom)) // prints "foo"
const unsub = store.sub(fooAtom, () => {
console.log('fooAtom value in store is changed')
})
// call unsub() to unsubscribe.
```
--------------------------------
### Todo Item Input and Atom Definition
Source: https://jotai.org/docs/guides/persistence
Defines the structure for a Todo item and the initial setup for managing todo atoms.
```typescript
const todoAtomsAtom = atom[]>([]);
type Todo = {
id: number;
title: string;
completed: boolean;
};
const addTodoAtom = atom(null, (get, set) => {
const newTodo = {
id: Date.now(),
title: '',
completed: false,
};
set(todoAtomsAtom, [...get(todoAtomsAtom), atom(newTodo)]);
});
const TodoItem: FC<{ atom: Atom }> = ({ atom }) => {
const [todo, setTodo] = useAtom(atom);
const [, setTodoAtoms] = useAtom(todoAtomsAtom);
const setTitle = (title: string) => {
setTodo((prev) => ({ ...prev, title }));
};
const toggleCompleted = () => {
setTodo((prev) => ({ ...prev, completed: !prev.completed }));
};
const removeTodo = () => {
setTodoAtoms((prev) => prev.filter((a) => a !== atom));
};
return (