# React quick start

Build a typed React counter that selects state and calls a store action without a provider.

Your store is a hook: create it with state and actions, then select what each component needs.

## Prerequisites

Use an existing browser-based React TypeScript project with:

- React 18 or later, with `react-dom` for rendering.
- React types (`@types/react`) 18 or later and the corresponding React DOM types.
- TypeScript 4.5 or later.
- Node.js 12.20.0 or later, as required by Zustand's package; your project's tooling can require a newer version.

These examples use the React JSX transform and a bundler that loads a TypeScript entry point from HTML.

## Install Zustand

Install the [`zustand`](https://bench-zustand-61.atloria.app/p/bench-zustand-61-pSJCWrWW5Y/developer/zustand) package in your project:

```bash
npm install zustand
```

## 1. Create a typed store

Use [`create`](https://bench-zustand-61.atloria.app/p/bench-zustand-61-pSJCWrWW5Y/developer/zustand#create) with the curried TypeScript form, `create<CounterState>()(…)`. Define your application's state and action together. The returned `useCounterStore` is the hook your components call.

```ts title="src/store.ts"
import { create } from 'zustand'

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

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

The store starts with `count` set to `0`. The functional update reads the current count and adds one. `set` merges the returned object into the state, so updating `count` keeps the `increment` action.

## 2. Select state and actions in components

Call the store hook with a selector. `Counter` receives the selected number; `Controls` receives the action function and passes it to the button's `onClick` handler.

```tsx title="src/App.tsx"
import { useCounterStore } from './store'

function Counter() {
  const count = useCounterStore((state) => state.count)
  return <h1>Count: {count}</h1>
}

function Controls() {
  const increment = useCounterStore((state) => state.increment)
  return <button onClick={increment}>+1</button>
}

export default function App() {
  return (
    <main style={{ minHeight: 200, padding: 24 }}>
      <Counter />
      <Controls />
    </main>
  )
}
```

Both components use the same store without a Zustand provider. When `count` changes, `Counter` re-renders with the new value. Each selector subscribes its component to the value it returns rather than the entire state.

## 3. Mount the counter

Give React a root element and load your entry point. In your project's HTML, use:

```html title="index.html"
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Zustand counter</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>
```

Render `App` into that element:

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

const container = document.getElementById('root')!

createRoot(container).render(
  <StrictMode>
    <App />
  </StrictMode>,
)
```

Start your project's development server and open its browser URL. You see **Count: 0** and a **+1** button. Click **+1**: the heading changes to **Count: 1**. Each subsequent click increases the displayed count by one.

You now have a typed store with colocated state and an action, two selector-based components, and a mounted counter without a provider. See the [live Zustand demo](https://zustand-demo.pmnd.rs/) for another counter example.

## Where to go next

- [State and actions](https://bench-zustand-61.atloria.app/p/bench-zustand-61-pSJCWrWW5Y/developer/state-and-actions) explains immutable updates and merging.
- [Selectors and subscriptions](https://bench-zustand-61.atloria.app/p/bench-zustand-61-pSJCWrWW5Y/developer/selectors-and-subscriptions) explains selecting multiple values and keeping selector outputs stable.
- [How Zustand works](https://bench-zustand-61.atloria.app/p/bench-zustand-61-pSJCWrWW5Y/developer/how-zustand-works) connects the store, actions, and component subscriptions.
