# 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 %}
