---
sidebar_position: 2
title: Define Model
---
# Define a Model

In the previous section, we demonstrated how to create a Model for a simple counter application. In this section, we will provide a detailed introduction on how to create a Model.

We can create a Model using the `model` API. For example, `model('foo')` creates a Model named `foo`. We can define the State and Actions included in the Model by calling the `define` function returned by `model('foo')`:


```js
import { model, useModel } from '@modern-js/runtime/model';

const fooModel = model('foo').define({
  state: {
    value: 'foo',
  },
  actions: {
    setValue: (state, payload){
      state.value = payload
    }
  }
});
```

:::info
- Actions in the Model cannot contain side-effect logic, such as requesting HTTP interfaces, accessing localStorage, etc.
- `setValue` directly modifies the input State, which seems to violate the definition of a pure function. However, Reduck uses [immer](https://github.com/immerjs/immer) internally to modify immutable objects, ensuring that this approach does not affect the immutability of the object, so `setValue` is still a pure function. Of course, you can also return a new object directly in the Action, but this approach will be more complex.

:::

The `define` function only describes the original structure of the Model, including the internally defined State, Actions, and so on. The `fooModel` returned by `define` is the actual Model object that is created. For example, although `setValue` has two parameters, when we call the `setValue` Action, we only need to pass in the `payload` parameter, because we are calling the Action method on `fooModel`, not the one described in the original structure of the Model. For more information, please refer to [Using Models](/guides/topic-detail/model/use-model).

In addition to object-type parameters, `define` can also receive function-type parameters. For example:

```js
import { model, useModel } from '@modern-js/runtime/model';

const fooModel = model('foo').define((context, utils) => {
  return {
    state: {
      value: 'foo',
    },
    actions: {
      setValue: (state, payload){
        state.value = payload
      }
    }
  }
});
```

When defining a Model using a function, the function automatically receives two parameters: `context` and `utils`. `context` is the context object of Reduck, which can obtain the `store` object, and `utils` provides a set of utility functions to facilitate the implementation of complex features such as Model communication.

Models support duplication. For example:

```ts
const barModel = fooModel('bar');
```

`barModel` is a new Model object created based on `fooModel`. Analogous to the concepts in object-oriented programming languages, `barModel` and `fooModel` are two instance objects created based on the same class. When the state management logic of two modules is the same, for example, two tab modules in the same page use the same data structure and logic, but the difference is that they obtain data from different interfaces, then you can create two different Model objects by duplicating the Model.

:::info Additional Information
For detailed definitions of the APIs mentioned in this section, please refer to [here](/apis/app/runtime/model/model_).
:::
