Skip to main content
The createStore function creates a new store instance that holds atom state. Stores are independent of React and can be used outside of components or passed to a Provider.

Signature

function createStore(): Store

Type Definitions

type Store = {
  get: <Value>(atom: Atom<Value>) => Value
  set: <Value, Args extends unknown[], Result>(
    atom: WritableAtom<Value, Args, Result>,
    ...args: Args
  ) => Result
  sub: (atom: AnyAtom, listener: () => void) => () => void
}

Parameters

No parameters.

Returns

store
Store
A store instance with three methods:

Examples

Basic Usage

import { createStore, atom } from 'jotai'

const store = createStore()
const countAtom = atom(0)

// Get atom value
const count = store.get(countAtom)
console.log(count) // 0

// Set atom value
store.set(countAtom, 1)
console.log(store.get(countAtom)) // 1

// Set with updater function
store.set(countAtom, (prev) => prev + 1)
console.log(store.get(countAtom)) // 2

Subscribe to Changes

import { createStore, atom } from 'jotai'

const store = createStore()
const countAtom = atom(0)

// Subscribe to changes
const unsub = store.sub(countAtom, () => {
  console.log('Count changed:', store.get(countAtom))
})

store.set(countAtom, 1) // Logs: "Count changed: 1"
store.set(countAtom, 2) // Logs: "Count changed: 2"

// Unsubscribe
unsub()
store.set(countAtom, 3) // No log

With Provider

import { createStore, Provider, atom, useAtom } from 'jotai'

const myStore = createStore()
const countAtom = atom(0)

// Initialize store before rendering
myStore.set(countAtom, 10)

function Counter() {
  const [count, setCount] = useAtom(countAtom)
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount((c) => c + 1)}>Increment</button>
    </div>
  )
}

function App() {
  return (
    <Provider store={myStore}>
      <Counter />
    </Provider>
  )
}

Outside React

import { createStore, atom } from 'jotai'

const store = createStore()
const countAtom = atom(0)

// Use in vanilla JavaScript
function incrementCount() {
  const current = store.get(countAtom)
  store.set(countAtom, current + 1)
}

// Subscribe to changes
store.sub(countAtom, () => {
  const count = store.get(countAtom)
  document.getElementById('count').textContent = count.toString()
})

incrementCount() // Updates the DOM

Server-Side Rendering

import { createStore, atom } from 'jotai'

const userAtom = atom(null)

// Create store per request
export async function getServerSideProps(context) {
  const store = createStore()

  // Fetch and initialize data
  const user = await fetchUser(context.params.id)
  store.set(userAtom, user)

  return {
    props: {
      store,
      // You'll need to serialize the store state separately
    },
  }
}

function Page({ store }) {
  return (
    <Provider store={store}>
      <UserProfile />
    </Provider>
  )
}

Derived Atoms

import { createStore, atom } from 'jotai'

const store = createStore()

const countAtom = atom(0)
const doubleAtom = atom((get) => get(countAtom) * 2)

const incrementAtom = atom(
  null,
  (get, set) => {
    set(countAtom, get(countAtom) + 1)
  }
)

console.log(store.get(doubleAtom)) // 0

store.set(incrementAtom)
console.log(store.get(countAtom)) // 1
console.log(store.get(doubleAtom)) // 2

Multiple Independent Stores

import { createStore, atom } from 'jotai'

const store1 = createStore()
const store2 = createStore()

const countAtom = atom(0)

store1.set(countAtom, 1)
store2.set(countAtom, 10)

console.log(store1.get(countAtom)) // 1
console.log(store2.get(countAtom)) // 10
// Completely independent state

Integration with External Libraries

import { createStore, atom } from 'jotai'
import EventEmitter from 'events'

const store = createStore()
const stateAtom = atom({ status: 'idle' })

const emitter = new EventEmitter()

// Bridge external events to Jotai
emitter.on('statusChange', (status) => {
  store.set(stateAtom, { status })
})

// Subscribe to Jotai changes and emit events
store.sub(stateAtom, () => {
  const state = store.get(stateAtom)
  emitter.emit('stateUpdated', state)
})

Notes

  • Each store is completely independent - atoms in different stores don’t share state
  • Stores can be used outside of React components
  • The store holds weak references to atom state, allowing garbage collection when atoms are no longer used
  • Store methods (get, set, sub) are synchronous
  • The sub method automatically mounts the atom and its dependencies
  • Calling set will trigger all subscribers of affected atoms
  • You typically don’t need to create stores manually - Provider creates one automatically

Build docs developers (and LLMs) love