# Build a React store

Use this page when a React component needs shared state, colocated actions, and a visible update. You create a hook with [`create`](https://bench-zustand-56.atloria.app/p/bench-zustand-56-D8Xr4XerWj/developer/zustand#create), select the state or action you need, and render the selected value.

## Prerequisites

Use React 18 or later, TypeScript in strict mode, and Zustand 5.0.15. Install Zustand in your React project:

```bash
npm install zustand
```

## Build and mount the store

Define state and its action together, then read the same store from separate mounted components. The page renders the current count and an `Increment` button; clicking the button updates every component that selects the count.

```tsx title="src/App.tsx"
import { createRoot } from 'react-dom/client'
import { create } from 'zustand'

type CounterStore = {
  count: number
  increment: () => void
}

const useCounterStore = create<CounterStore>((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
}))

function CounterValue() {
  const count = useCounterStore((state) => state.count)

  return <p>Count: {count}</p>
}

function CounterControls() {
  const increment = useCounterStore((state) => state.increment)

  return (
    <button type="button" onClick={increment}>
      Increment
    </button>
  )
}

function Counter() {
  return (
    <main>
      <CounterValue />
      <CounterControls />
    </main>
  )
}

const rootElement = document.getElementById('root')

if (!rootElement) {
  throw new Error('The root element is missing')
}

createRoot(rootElement).render(<Counter />)
```

![The mounted counter displays Count: 0 and an Increment button in separate components.](https://atloriaassets.blob.core.windows.net/assets/a438221c-c1af-407c-b9e6-a56c986db846/fb5ff6993ef4399a4529d5e9f8322035.png)

The initial render shows `Count: 0` and the `Increment` button. The two components share the hook, so each click calls the colocated action and updates the value component.

See the [live demo](https://zustand-demo.pmnd.rs/) or [its React example source](https://github.com/pmndrs/zustand/blob/d7a5583cffd80af515f7dfb69583c95cbdc9e2ce/examples/demo) for a complete application using the same store shape.

## Choose selectors for the values you use

For selector granularity, equality, and stable computed results, see [Selectors and rendering](https://bench-zustand-56.atloria.app/p/bench-zustand-56-D8Xr4XerWj/developer/selectors-and-rendering).

Keep updates immutable. Zustand shallow-merges the object returned by `set` by default, but nested objects need an explicit nested merge. Passing the replace flag replaces the complete state model, including actions, so use that form only when replacing the whole store is intentional. See [Immutable state updates](https://bench-zustand-56.atloria.app/p/bench-zustand-56-D8Xr4XerWj/developer/immutable-state-updates).

## Where to go next

- [Selectors and rendering](https://bench-zustand-56.atloria.app/p/bench-zustand-56-D8Xr4XerWj/developer/selectors-and-rendering) — control re-renders for computed selections.
- [Typed store patterns](https://bench-zustand-56.atloria.app/p/bench-zustand-56-D8Xr4XerWj/developer/typed-store-patterns) — organize larger TypeScript stores.
- [Create a vanilla store](https://bench-zustand-56.atloria.app/p/bench-zustand-56-D8Xr4XerWj/developer/create-a-vanilla-store) — create a store without a React hook.
- [Split a store into slices](https://bench-zustand-56.atloria.app/p/bench-zustand-56-D8Xr4XerWj/developer/split-a-store-into-slices) — divide a growing store into smaller creators.
