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'):

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 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.

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

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:

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.

Additional Information

For detailed definitions of the APIs mentioned in this section, please refer to here.