Model communication refers to communication between different Models, as well as communication between Effects and Actions within the same Model.
Models are not isolated from each other and can communicate with each other. There are mainly two scenarios:
Here, we will transform the simple counter application in the Quick Start section into a counter application that allows you to set the step frequency. By setting the step frequency, you can affect the magnitude of each counter increase.
We abstract two Models, stepModel
(step frequency) and counterModel
(counter):
stepModel
declares only one state
, with an initial value of 1.
counterModel
loads stepModel
with the use
function, and retrieves the returned subscribeStep
function to listen for changes to the stepModel
state. onMount
is a hook function that is executed after the Model is mounted. counterModel
begins to subscribe to the state changes of stepModel
after it has been mounted, and prints out the latest value of stepModel
.
counterModel
accesses stepModel
using the use
function, and in the add
function, the current value of stepModel
(step frequency) can be obtained to perform increments using this value.
When you need to access the state of another Model, you must call use
during the actual execution phase of the current Actions or Effects function (in this example, the add
function) to ensure that the obtained State is the latest value. Therefore, although we also call use(stepModel)
in the callback function of define
, we do not destructure the state
value of stepModel
because the callback function of define
is executed during the mounting phase of the Model, and at this time, the state
of stepModel
obtained may be different from the value obtained when add
is executed.
Modify App.tsx:
Modern.js has enabled auto-generate actions by default, so even though there are no Actions defined manually in the stepModel
, the auto-generated setState
can still be used.
The final effect is as follows:
In the previous example of counterModel
, we called use
within the Actions function to get other Model objects. If we only need to call Actions of other Models, we can also use use
to get the Actions of Models in the define
callback function because Actions are functions and there is no issue of value expiration. For example:
Here, we no longer need to repeatedly get the barModel
object in loadA
and loadB
, which simplifies the code logic.
Communication within a Model can also be divided into two main scenarios:
In the Managing Side Effects section, we demonstrated how Effects functions call Actions functions.
Here we provide another example:
In this example, the two Effects functions of fooModel
need to call their own Actions functions. Here, we have called use
once in each Effects function. Why can't we use use
to get the Actions of the Model itself in the define
callback function, as in the example of Model communication? This is because when calling use
to get a Model, it first checks whether the Model has been mounted. If it has not been mounted, the mounting logic will be executed first.
The define
callback function is executed during the mounting phase, so calling use
to get the Model itself during the mounting phase will result in an infinite loop (which will throw an error in the actual execution process). Therefore, you must not call use
in the define
callback function to get the Model itself.
However, we can use the onMount
hook function to get the Model itself through use
after the Model has been mounted:
In this way, we can also simplify the code.