> For the complete documentation index, see [llms.txt](https://docs.sentre.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sentre.io/development/model-and-controllers.md).

# Model & Controllers

> ### Single model - Multiple controllers

## Model

Typically, the model always has a single file that is to merge all the controllers' states into the store.

```typescript
// model/index.ts

import { configureStore } from '@reduxjs/toolkit'
import { devTools, bigintSerializationMiddleware } from 'shared/devTools'

import main from 'app/model/main.controller'

/**
 * Isolated store
 */
const model = configureStore({
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware(bigintSerializationMiddleware),
  devTools: devTools(process.env.REACT_APP_ID as string),
  reducer: {
    main,
  },
})

export type AppState = ReturnType<typeof model.getState>
export type AppDispatch = typeof model.dispatch
export default model
```

Following the template, your DApp's state is isolated in a store named `myapp`. If you installed Redux Devtool, you are able to inspect the `myapp` states clearly.

![The isolated states of myapp.](/files/uCz8rtzsnIisOXWLbI8P)

Additionally, the model will merge all states in `reducer` (i.e. `main` is the current state declared in the reducer) which are exported from controllers. To import a new state, you merely need to add the state into the reducer.

## Controllers

Controllers typically are to fetch raw data, process it to good forms, and export it to the model.

```typescript
// main.controller.ts

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'

/**
 * Interface & Utility
 */

export type State = {
  counter: number
}

/**
 * Store constructor
 */

const NAME = 'main'
const initialState: State = {
  counter: 0,
}

/**
 * Actions
 */

export const increaseCounter = createAsyncThunk<State, void, { state: any }>(
  `${NAME}/increaseCounter`,
  async (_, { getState }) => {
    const {
      main: { counter },
    } = getState()
    return { counter: counter + 1 }
  },
)

/**
 * Usual procedure
 */

const slice = createSlice({
  name: NAME,
  initialState,
  reducers: {},
  extraReducers: (builder) =>
    void builder.addCase(
      increaseCounter.fulfilled,
      (state, { payload }) => void Object.assign(state, payload),
    ),
})

export default slice.reducer
```

By the example, the name and struct of the state had been assigned at lines 15, 16. The function `increaseCounter` is to compute and return the next state partially which will mutate the current state in slice (i.e. line 38 to build a state and line 44 to catch the next state from `increaseCounter`).

{% hint style="info" %}
Examine [Best Practices](/best-practices.md) for more examples.
{% endhint %}
