# States

## What are states?

States allow you to store user data (for example, a newly entered nickname in a scope). The states also store data about the current scopes (`state.__currentScope`). The data is stored locally until the project is reloaded, but you can also use your state getter to persist the data in your database

## Using states

To use state in the controller/scope, use `@GetState` property decorator. The state type is your own object, so you can use interfaces to describe the state type. Then you can use `this.state`  expression in your handlers to get/set current user state

{% code title="app.controller.ts" %}

```typescript
import { Controller, GetState, OnCommand } from 'nestgram';
import { AppService } from './app.service';

export interface IMyState {
  counter?: number;
}

@Controller()
export class AppController {
  @GetState() state: IMyState;
  constructor(private readonly appService?: AppService) {}

  @OnCommand('start')
  start(): string {
    this.state.counter = (this.state.counter || 0) + 1;
    return 'Hello!';
  }

  @OnCommand('stats')
  stats(): string {
    return `You entered /start ${this.state.counter || 0} times`;
  }
}
```

{% endcode %}

## Default state value

You can set a default state value per user if it has no state. In the `main.ts` file, call the `.setDefaultValue` stateStore method

{% hint style="info" %}
.setDefaultValue method takes argument: default value (object)
{% endhint %}

{% code title="main.ts" %}

```typescript
import { NestGram, stateStore } from 'nestgram';
import { AppModule } from './app.module';
import * as config from 'config';

async function bootstrap(): Promise<void> {
  const bot: NestGram = new NestGram(config.get<string>('botToken'), AppModule);

  stateStore.setDefaultValue({
    count: 0,
  });

  await bot.start();
}

bootstrap();
```

{% endcode %}

## Custom state getter

You can set your own state getter (e.g. with database work). In the `main.ts` file, call the `.setCustomGetter` **stateStore method** and pass your custom method as argument. It's a function (it can be async) that takes some arguments (below hint). This function is called when a handler is processing an update and state is required in its controller

{% hint style="info" %}
.setCustomGetter method takes argument: your custom getter (method) you want to set. It takes [these arguments](#undefined). This function should return a state (object)
{% endhint %}

#### Your custom method can take arguments:

<table><thead><tr><th width="150" data-type="number">Argument</th><th>Description</th></tr></thead><tbody><tr><td>1</td><td>User ID</td></tr><tr><td>2</td><td>Params from the handler</td></tr><tr><td>3</td><td>Default value</td></tr></tbody></table>

{% code title="main.ts" %}

```typescript
import { NestGram, stateStore } from 'nestgram';
import { AppModule } from './app.module';
import * as config from 'config';

async function bootstrap(): Promise<void> {
  const bot: NestGram = new NestGram(config.get<string>('botToken'), AppModule);

  stateStore.setCustomGetter(
    async <T = any>(userId: number, params?: any, defaultValue?: any): Promise<T> => {
      let state: T = {} as T;
      // ... (your code to get state)
      return state;
    }
  );

  await bot.start();
}

bootstrap();
```

{% endcode %}

## Custom state setter

You can set your own state getter (e.g. to save the new state to the db). In the `main.ts` file, call the `.setCustomSetter` **stateStore method** and pass your custom method as argument. It's a function (it can be async) that takes some arguments (below hint). This function is called when the state changes

{% hint style="info" %}
.setCustomSetter method takes argument: your custom setter (method) you want to set. It takes [these arguments](#undefined)
{% endhint %}

#### Your custom method can take arguments:

<table><thead><tr><th width="150" data-type="number">Argument</th><th>Description</th></tr></thead><tbody><tr><td>1</td><td>User ID</td></tr><tr><td>2</td><td>The name of the changed state property</td></tr><tr><td>3</td><td>The value of the changed state property</td></tr><tr><td>4</td><td>Params from the handler</td></tr></tbody></table>

{% code title="main.ts" %}

```typescript
import { NestGram, stateStore } from 'nestgram';
import { AppModule } from './app.module';
import * as config from 'config';

async function bootstrap(): Promise<void> {
  const bot: NestGram = new NestGram(config.get<string>('botToken'), AppModule);

  stateStore.setCustomSetter(
    async (userId: number, name: string, value: string, params?: any): Promise<any> => {
      // save new state to db ...
    }
  );

  await bot.start();
}

bootstrap();
```

{% endcode %}


---

# 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://degreetpro.gitbook.io/nestgram/nestgram-features/states.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.
