Skip to main content
atomWithDefault creates a writable atom that derives its default value from other atoms. It can be reset to recompute the default.

Import

import { atomWithDefault } from 'jotai/utils'

Signature

function atomWithDefault<Value>(
  getDefault: (get: Getter, options: Options) => Value,
): WritableAtom<Value, [DefaultSetStateAction<Value>], void>

type DefaultSetStateAction<Value> =
  | Value
  | typeof RESET
  | ((prev: Value) => Value | typeof RESET)

Parameters

getDefault
(get: Getter, options: Options) => Value
required
A function that derives the default value from other atoms using get. This function is called when the atom is first read or after being reset

Return Value

Returns a writable atom that:
  • Initially returns the value from getDefault
  • Can be updated with new values
  • Can be reset using the RESET symbol to recompute the default

Usage Example

import { atom, useAtom } from 'jotai'
import { atomWithDefault, RESET } from 'jotai/utils'

const baseAtom = atom(0)
const derivedAtom = atomWithDefault((get) => get(baseAtom) * 2)

function Component() {
  const [base, setBase] = useAtom(baseAtom)
  const [derived, setDerived] = useAtom(derivedAtom)

  return (
    <div>
      <p>Base: {base}</p>
      <p>Derived: {derived}</p>
      <button onClick={() => setBase((b) => b + 1)}>Increment Base</button>
      <button onClick={() => setDerived(100)}>Set Derived to 100</button>
      <button onClick={() => setDerived(RESET)}>Reset Derived</button>
    </div>
  )
}

Advanced Example

import { atom } from 'jotai'
import { atomWithDefault, atomWithStorage, RESET } from 'jotai/utils'

// Server-provided default
const serverConfigAtom = atom(async () => {
  const response = await fetch('/api/config')
  return response.json()
})

// User preferences with server default
const userPreferencesAtom = atomWithDefault(
  async (get) => await get(serverConfigAtom)
)

function Settings() {
  const [preferences, setPreferences] = useAtom(userPreferencesAtom)

  const handleSave = () => {
    // Save custom preferences
    setPreferences({ theme: 'dark', language: 'en' })
  }

  const handleResetToDefault = () => {
    // Reset to server defaults
    setPreferences(RESET)
  }

  return (
    <div>
      <div>Theme: {preferences.theme}</div>
      <button onClick={handleSave}>Save Custom</button>
      <button onClick={handleResetToDefault}>Reset to Server Default</button>
    </div>
  )
}

Overriding Storage Defaults

import { atom } from 'jotai'
import { atomWithDefault, atomWithStorage, RESET } from 'jotai/utils'

// Remote configuration
const remoteConfigAtom = atom({ color: 'blue', size: 'medium' })

// Local override with remote default
const localConfigAtom = atomWithDefault(
  (get) => get(remoteConfigAtom)
)

function ConfigEditor() {
  const [remoteConfig] = useAtom(remoteConfigAtom)
  const [localConfig, setLocalConfig] = useAtom(localConfigAtom)

  return (
    <div>
      <p>Remote: {JSON.stringify(remoteConfig)}</p>
      <p>Local: {JSON.stringify(localConfig)}</p>
      
      <button onClick={() => setLocalConfig({ color: 'red', size: 'large' })}>
        Override
      </button>
      <button onClick={() => setLocalConfig(RESET)}>
        Reset to Remote
      </button>
    </div>
  )
}

Fallback Pattern

import { atom } from 'jotai'
import { atomWithDefault, RESET } from 'jotai/utils'

const userNameAtom = atomWithStorage<string | null>('userName', null)
const defaultNameAtom = atom('Guest')

const displayNameAtom = atomWithDefault((get) => {
  return get(userNameAtom) ?? get(defaultNameAtom)
})

function UserDisplay() {
  const [displayName, setDisplayName] = useAtom(displayNameAtom)

  return (
    <div>
      <p>Hello, {displayName}!</p>
      <button onClick={() => setDisplayName('Alice')}>Set Name</button>
      <button onClick={() => setDisplayName(RESET)}>Reset</button>
    </div>
  )
}

Notes

  • The default is recomputed when you set the atom to RESET
  • Once overwritten, the atom will not automatically update when dependencies change
  • The getDefault function can be async and return a Promise
  • Useful for implementing “reset to default” functionality
  • The atom maintains its overridden value until reset

Build docs developers (and LLMs) love