useModel
can be used to obtain the State, Actions, and other information of the Model. When the State of the Model is modified by Actions, any other components that use the Model will automatically re-render.
In the counter example in Quick Start, we have demonstrated the use of useModel
and will not repeat it here.
useModel
supports passing multiple Models, and the State and Actions of multiple Models will be merged and returned as the result. For example:
state
and actions
value are:
useModel
also supports selector operations on State and Actions to filter or rename State and Actions. For example:
We use stateSelector
to rename the states with the same name in fooModel
and barModel
. We use actionsSelector
to filter out the Actions of barModel
.
If only actionsSelector
needs to be set, you can set stateSelector
to undefined
as a placeholder. For example:
useStaticModel
can be used to obtain the Model and use the state of the Model as a static state. This ensures that the State accessed by the component is always the latest value, but the change of the Model's State does not cause the current component to re-render.
The usage of useStaticModel
is exactly the same as useModel
.
Consider the following scenario: there is an Input component responsible for user input, and another Search component responsible for executing a search operation after the user input information is entered and the search button is clicked. We do not want the state changes during the user input process to cause Search to re-render. In this case, useStaticModel
can be used:
Do not destructure the state
returned by useStaticModel
. For example, changing it to the following code:
const [{input}] = useStaticModel(searchModel);
will always get the initial value of Input.
useStaticModel
is also suitable for use with animation libraries such as react-three-fiber, because binding fast-changing states in animation component UI can easily cause performance issues. In this case, you can choose to use useStaticModel
, which only subscribes to the State but does not cause the view component to re-render. Here is a simplified example:
Using React's refs can also achieve similar effects. In fact, useStaticModel
also uses refs internally. However, using useStaticModel
directly helps decouple the state management logic from the component and converge it into the Model layer.
The complete sample code can be found here.
useLocalModel
can be used to obtain the Model and use the state of the Model as local state. At this time, the change of the Model State only causes the current component to re-render, but does not cause other components that use the Model to re-render. The effect is similar to managing state through useState
in React, but it can decouple the state management logic from the component and converge it into the Model layer.
The usage of useLocalModel
is exactly the same as useModel
.
For example, we modify the code of the counter application and add a counter component LocalCounter
with local state:
Click the add
button of Counter
and LocalCounter
respectively, and the states of the two do not affect each other:
The complete sample code can be found here.
In actual business scenarios, sometimes we need to use Model outside of React components, such as accessing State and executing Actions in utility functions. At this time, we need to use the Store. The Store is a low-level concept that users generally cannot touch. It is responsible for storing and managing the entire application's state. Reduck's Store is based on Redux's Store implementation and adds Reduck-specific APIs, such as use
.
First, call useStore
in the component to obtain the store
object used by the current application and mount it to a variable outside the component:
You can obtain the Model object through store.use
, and the usage of store.use
is the same as useModel
. Taking the counter application as an example, we perform an increment operation on the counter value every 1 second outside the component tree:
The complete sample code can be found here.
If the Store object is manually created through createStore
, there is no need to obtain it through useStore
in the component, and it can be used directly.
For detailed API definitions related to this section, please refer to here.