# 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.](https://3606779243-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDSuDatsiBSDcGYiS7br6%2Fuploads%2FzskpzhyymFh6yoAT5oKX%2FScreen%20Shot%202021-11-22%20at%2000.31.38.png?alt=media\&token=e2bf1bc6-8197-4f8b-a637-a0e7784923e2)

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](https://docs.sentre.io/best-practices) for more examples.
{% endhint %}
