### 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 (
  • { setTodo((oldValue) => ({ ...oldValue, task: e.target.value })); }} /> { setTodo((oldValue) => ({ ...oldValue, done: !oldValue.done })); }} />
  • ); }; const TodoList = () => { const [todoAtoms, dispatch] = useAtom(todoAtomsAtom); return (
      {todoAtoms.map((todoAtom) => ( dispatch({ type: 'remove', atom: todoAtom })} /> ))}
    ); }; 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 (
    { setTodo((oldValue) => ({ ...oldValue, task: e.target.value })) }} /> { setTodo((oldValue) => ({ ...oldValue, done: !oldValue.done })) }} />
    ) } const TodoList = () => { const [todoAtoms, dispatch] = useAtom(todoAtomsAtom) return (
      {todoAtoms.map((todoAtom) => ( dispatch({ type: 'remove', atom: todoAtom })} /> ))}
    ) } 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 (
  • setTitle(e.target.value)} placeholder="Enter title..." />
  • ); }; ``` -------------------------------- ### Basic Jotai Effect Setup with React Provider Source: https://jotai.org/docs/extensions/effect Pass the store to both `observe` and the `Provider` to ensure the effect is mounted to the correct store. This is essential for managing Jotai state and effects within a React application. ```javascript import { Provider } from 'jotai/react' import { createStore } from 'jotai/vanilla' import { observe } from 'jotai-effect' const store = createStore() const unobserve = observe((get, set) => { // Effect logic here set(logAtom, `someAtom changed: ${get(someAtom)}`) }, store) // Ensure the store is passed to the Provider ... ``` -------------------------------- ### Vite React TypeScript Starter Dependencies Source: https://jotai.org/docs/extensions/location This `package.json` file lists the necessary dependencies for a Vite-based React TypeScript project, including `jotai` and `jotai-location`. ```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": { "jotai": "1.9.2", "react": "^18.3.1", "react-dom": "^18.3.1", "jotai-location": "0.2.0" }, "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" } } ``` -------------------------------- ### Simple localStorage Persistence Pattern Source: https://jotai.org/docs/guides/persistence A basic pattern to persist a string atom to localStorage. It manually handles getting and setting the item. ```javascript const strAtom = atom(localStorage.getItem('myKey') ?? 'foo') const strAtomWithPersistence = atom( (get) => get(strAtom), (get, set, newStr) => { set(strAtom, newStr) localStorage.setItem('myKey', newStr) }, ) ```