# What is zoov

[Zoov](https://github.com/InfiniteXyy/zoov) is a State management solution build on top of [zustand](https://github.com/pmndrs/zustand). So I called it:  `Zoov = Zustand + Module`

Compared to zustand, zoov improves it's capability in these fields:

### TypeScript first

Zoov was built for TypeScript users. Type inference are put in the first place in all it's API's design. You can expect a good Developing Experience in using zoov.

For Example:

```typescript
const module = defineModule({ count: 0 })
    // The `state` here will have type { count: number }
    .actions({ add: (state, amount: number)=> ... })
    // The `getActions` here will have type { add(amount: number): void }
    .methods(({ getActions }) => ({}))
    .build()

```

### Mutable state

Though Immutable state is always recommended in React world. In my opinion, mutable state is usually easier and cleaner. So, I decided to make state **mutable** with the help of [immer](https://github.com/immerjs/immer).

In zoov, mutable state is restricted in a smaller scope (Only in module actions), it will not affact the main concept of React.

```typescript
module.actions({
  addTodo: (state, title: string) => {
    state.todos.push({ title, checked: false });
  },
});
```

### Incremental API

Zustand is simple, and zoov doesn't intend to complicate your code base. From my perspective, zoov is even **simpler** and **easier** to use.

For example, if you want to create a global store to share a count value. One line of js code is enough

```typescript
const module = defineModule({ count: 0 }).build()
```

To use it in component

```tsx
const [{ count }, { $setState }] = module.use()

// $setState is the internal action of a module
const add = $setState("count", v => v + 1)
```

In zoov, all the features are optional and can be added on demand. For example:

* If you found that a state mutation is shared among different components, you can define a module action/method to reduce code duplication.
* If you want to use async action or even take advantage of rxjs, you can put these code in module methods.
* If you want to persist the store or debug the store with redux-devtools, you can easily do it leveraging the [zustand middleware](https://github.com/pmndrs/zustand#middleware)

### Context & Scoped

Zoov designed it's context API with the concept of Algebraic Effect, if you have not heard of this, you can read this [post](https://overreacted.io/algebraic-effects-for-the-rest-of-us/).

Most cases, you don't need a scope context, each module has a global scope by default. But if you want to modify the default state, or compose a custom middleware, you can define a provider to create a local context.

You don't need to worry about the performance issue, the scope will not be built until you use it in.

The Context is composable, the child context will inhrerit evertying from the parent context. You can read more info from [Context & Scope](#provider-and-scoped-state)

```tsx
const Provider= defineProvider((handle) => {
  handle(CounterModule, {
    defaultValue: { count: 1 },
    middleware: (store) => persist(store, { name: 'count2' }),
  });
  
   handle(AnotherModule, {
    defaultValue: { ... },
  });
});

```

### Flexible

Zoov is a React hook library, but it's state is stored outside React, so it's possible to get/set the module state in any function.

This is extremely useful when you want to want to define a static function to mutate the module state, or get the latest value in a callback function.

```typescript
function add() {
  module.getActions().$setState("count", v => v + 1)
}

useEffect(() => {
  const timer = setTimeout(() => {
    // Get the latest module state
    console.log(module.getState());
    // Mutate the store via a static function
    add()
  }, 1000);
  return () => clearTimeout(timer);
}, []);
```

Sometimes, a module state is handled by a [provider](#context-and-scoped). But it's also possible to attach to the module scope , with `useScopeContext`

```typescript
const context = useScopeContext();
const actions= module.getActions(context);
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://infinitexyy.gitbook.io/zoov/introduction/what-is-zoov.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
