# Use a vanilla store in React

Create a standalone store, then use a React component to display and update a selected value from it.

Use this pattern when non-React code updates state that a mounted React component displays; for how vanilla and hook-bound stores differ, see [React and vanilla stores](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/react-and-vanilla-stores).

## Create the store and mount its React consumer

Install [`zustand`](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/zustand) in your React project; see [React and vanilla stores](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/react-and-vanilla-stores) for the package entry-point distinctions, including [`zustand/vanilla`](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/zustand-vanilla).

```bash
npm install zustand
```

In `CounterApp.tsx`, [`createStore`](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/zustand#createstore) owns the count and [`useStore`](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/zustand#usestore) selects it for the mounted component. Unlike a hook-bound counter, this example has a browser timer update the store outside the component.

```tsx
import { useEffect } from 'react'
import { createRoot } from 'react-dom/client'
import { useStore } from 'zustand'
import { createStore } from 'zustand/vanilla'

type CounterStore = {
  count: number
}

const counterStore = createStore<CounterStore>()(() => ({ count: 0 }))

function Counter() {
  const count = useStore(counterStore, (state) => state.count)

  useEffect(() => {
    const interval = window.setInterval(() => {
      counterStore.setState((state) => ({ count: state.count + 1 }))
    }, 1000)

    return () => window.clearInterval(interval)
  }, [])

  return (
    <section>
      <output aria-live="polite">{count}</output>
    </section>
  )
}

function App() {
  return <Counter />
}

const container = document.getElementById('root')!
createRoot(container).render(<App />)
```

Add `<div id="root"></div>` to the page and use this file as your browser entry point. In the browser, the mounted output starts at `0` and advances once per second as the timer updates the store. The timer callback runs independently of React rendering; the selected count causes the component to display each update.

## Selector and store API

For the comparison of vanilla and hook-bound store APIs, see [React and vanilla stores](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/react-and-vanilla-stores). This page focuses on selecting the value the mounted React view renders.

| Option | Type | Default | What it does |
| --- | --- | --- | --- |
| `useStore` selector | `(state: CounterStore) => U` | Identity selector when omitted | Returns the selected value for the component. This example selects `count`. |

The initializer's `set` updates state immutably. For an object update such as `{ count: nextCount }`, Zustand shallowly merges the returned fields into the current state; keep nested updates immutable as well. The vanilla store's `subscribe` method is available for non-React subscribers and returns an unsubscribe function.

## Pitfalls

- If middleware changes `set` or `get`, those changes do not apply to the vanilla store's `setState` and `getState` methods. See [Subscribe outside React](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/subscribe-outside-react).
- In Next.js, avoid sharing a global store across simultaneous server requests, and do not read or write it from React Server Components. See [Set up Zustand in Next.js](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/set-up-zustand-in-nextjs).

## See it running

Try the [Zustand live demo](https://zustand-demo.pmnd.rs/) to see Zustand running in a browser.

## Related

- [React and vanilla stores](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/react-and-vanilla-stores)
- [Create and bind a React store](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/create-and-bind-a-react-store)
- [Select state efficiently](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/select-state-efficiently)
- [Update nested state](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/update-nested-state)
