# Store

```ts
import { Store } from 'cx/data';
```



The **Store** is the central state container in CxJS. It holds all application data and notifies widgets when data changes, triggering automatic UI updates.

## Accessing the Store

Every CxJS widget has access to the store through its instance. In event handlers, access it via the second parameter:

```tsx
import { createModel, Store } from "cx/data";
import { Button } from "cx/widgets";

interface PageModel {
  count: number;
}

const m = createModel<PageModel>();

export default (
  <div class="flex flex-col gap-4">
    <div class="flex gap-2 items-center">
      <Button
        onClick={(e, { store }) => {
          store.set(m.count, (store.get(m.count) || 0) - 1);
        }}
      >
        -
      </Button>
      <span class="w-12 text-center" text={m.count} />
      <Button
        onClick={(e, { store }) => {
          store.set(m.count, (store.get(m.count) || 0) + 1);
        }}
      >
        +
      </Button>
    </div>
    <div class="p-3 bg-muted rounded text-sm">
      <strong>Store content</strong>
      <pre class="mt-2" text={(data) => JSON.stringify(data, null, 2)} />
    </div>
  </div>
);

```

The store is available in event handlers like `onClick`, `onChange`, and others. Use `store.get()` to read values and `store.set()` to write them.

When using typed models with `createModel`, all store methods are fully typed. TypeScript catches type mismatches at compile time:

```tsx
interface PageModel {
  count: number;
  name: string;
}

const m = createModel<PageModel>();

store.set(m.count, 5); // ✓ OK
store.set(m.count, "five"); // ✗ Type error
store.set(m.name, "John"); // ✓ OK
```

## Store Methods

The store provides several methods for working with data:

| Method                         | Description                                                        |
| ------------------------------ | ------------------------------------------------------------------ |
| `get(accessor)`                | Returns the value at the given path                                |
| `set(accessor, value)`         | Sets the value at the given path                                   |
| `init(accessor, value)`        | Sets the value only if currently undefined                         |
| `update(accessor, fn)`         | Applies a function to the current value and stores the result      |
| `delete(accessor)`             | Removes the value at the given path                                |
| `toggle(accessor)`             | Inverts a boolean value                                            |
| `copy(from, to)`               | Copies a value from one path to another                            |
| `move(from, to)`               | Moves a value from one path to another                             |
| `batch(fn)`                    | Batches multiple updates, notifying listeners only once at the end |
| `silently(fn)`                 | Executes updates without triggering any notifications              |
| `notify(path?)`                | Manually triggers change notifications                             |
| `subscribe(fn)`                | Registers a listener for changes; returns an unsubscribe function  |
| `ref(accessor, defaultValue?)` | Creates a reactive reference to store data                         |
| `getData()`                    | Returns the entire store data object                               |

```tsx
import { createModel } from "cx/data";
import { Button } from "cx/widgets";

interface PageModel {
  user: {
    name: string;
    age: number;
  };
}

const m = createModel<PageModel>();

export default (
  <div class="flex flex-col gap-4">
    <div class="flex flex-wrap gap-2">
      <Button
        onClick={(e, { store }) => {
          store.set(m.user.name, "John");
        }}
      >
        set(m.user.name, "John")
      </Button>
      <Button
        onClick={(e, { store }) => {
          store.update(m.user.age, (age) => (age || 0) + 1);
        }}
      >
        update(m.user.age, age =&gt; age + 1)
      </Button>
      <Button
        onClick={(e, { store }) => {
          store.delete(m.user.name);
        }}
      >
        delete(m.user.name)
      </Button>
      <Button
        onClick={(e, { store }) => {
          store.set(m.user, { name: "Jane", age: 25 });
        }}
      >
        set(m.user, &#123;...&#125;)
      </Button>
    </div>
    <div class="p-3 bg-muted rounded text-sm">
      <strong>Store content</strong>
      <pre class="mt-2" text={(data) => JSON.stringify(data, null, 2)} />
    </div>
  </div>
);

```

## Immutability

The store treats all data as immutable. When you call `set()` or `update()`, CxJS creates new object references along the path to the changed value. This enables efficient change detection — widgets only re-render when their bound data actually changes.

<Note type="warning">
  When updating objects or arrays, you must create new instances. Mutating
  existing objects directly will not trigger UI updates.
</Note>

```tsx
// Updating an object - spread the original and override properties
store.update(m.user, (user) => ({ ...user, name: "John" }));

// Adding to an array - create a new array
store.update(m.items, (items) => [...items, newItem]);

// Removing from an array - filter returns a new array
store.update(m.items, (items) => items.filter((item) => item.id !== id));
```

## Immer Integration

For complex nested updates, manually spreading objects can become tedious. The `cx-immer` package provides a `mutate` method that lets you write mutable-style code while CxJS handles immutability behind the scenes:

```tsx
import { enableImmerMutate } from "cx-immer";
enableImmerMutate();

// Now you can use mutate with mutable syntax
store.mutate(m.user, (user) => {
  user.name = "John";
  user.scores.push(100);
  user.address.city = "New York";
});
```

The `mutate` method uses [Immer](https://immerjs.github.io/immer/) to produce immutable updates from mutable code. This is especially useful when updating deeply nested structures or performing multiple changes at once.

## Creating a Store

In most applications, CxJS creates the store automatically. If you need to create one manually (for testing or advanced scenarios), use the `Store` constructor:

```tsx
import { Store } from "cx/data";

const store = new Store({
  data: {
    count: 0,
    user: { name: "Guest" },
  },
});

// Read and write data
const count = store.get(m.count);
store.set(m.count, count + 1);
```