# Store

Source: https://signy.dev/documentation/1/reactivity/store/

Deep reactive state for nested objects and arrays.

## Create a store

A store wraps an object. Reads through `.state` are tracked down to each property, so a binding updates only when the property it reads changes.

```js
const cart = store({
  items: [] as { id: number; name: string; qty: number }[],
  coupon: '',
});

cart.state.items.length; // tracked
```

## Write with set()

`set()` takes a path and a value. A function as the last argument receives the previous value.

```js
cart.set('coupon', 'SPRING');
cart.set('items', (items) => [...items, { id: 1, name: 'Tea', qty: 1 }]);
cart.set('items', 0, 'qty', (qty) => qty + 1);
```

`merge(partial)` sets several top level keys, `update(fn)` replaces the whole state, and `unwrap()` returns a plain copy.

## Example

```js
const { Component, application, html, store, For } = Signy;

class Cart extends Component {
  cart = store({
    items: [
      { id: 1, name: "Tea", qty: 1 },
      { id: 2, name: "Biscuits", qty: 2 },
    ],
  });

  add(index) {
    this.cart.set("items", index, "qty", (qty) => qty + 1);
  }

  render() {
    return html`
      <ul>
        ${For({
          each: () => this.cart.state.items,
          children: (item, index) => html`
            <li>
              ${item.name}: ${() => this.cart.state.items[index()].qty}
              <button class="small" onClick=${() => this.add(index())}>+1</button>
            </li>
          `,
        })}
      </ul>
      <p>${() => this.cart.state.items.reduce((sum, item) => sum + item.qty, 0)} items in the cart</p>
    `;
  }
}

application(Cart).mount("#store-cart");
```

## produce()

`produce()` lets you write a change as a mutation of a draft.

```js
cart.set('items', produce((items) => {
  items.push({ id: 3, name: 'Jam', qty: 1 });
}));
```
