Is it appropriate to wrap functions that don't mutate observables with the action
#3844
-
I've been using BackgroundI have enabled the following configuration options in the project, much like React's configure({
observableRequiresReaction: true,
// ...
}); My store currently looks like this, it keeps observable states and handles the aggregation of some business logic involving interactions with the server(For clarity, I have simplified the following code): class CounterStore {
constructor() {
this.counter = 0;
makeObservable(this, {
counter: observable,
increment: action,
});
}
increment() {
this.counter++;
}
// ...
private serializeParams() {
return JSON.stringify({
userCounter: this.counter,
// ...
// some args are view-unrelated.
});
}
async submit() {
const params = this.serializeParams();
await saveServiceApi(params); // interact with server
// ...
}
} My business component looks something like this, very straightforward. import { observer } from "mobx-react"
import './App.css'
import store from "./store"
function App() {
const handleClick = () => {
store.increment() // View updates.
}
const handleSubmit = () => {
store.submit() // Biz logic: gather info and save
}
return (
<>
<div className="card">
<button onClick={handleClick}>
count is {store.counter}
</button>
<button onClick={handleSubmit}>
submit
</button>
</div>
</>
)
}
const ObservedApp = observer(App)
export default ObservedApp Then I found the ConfusionAfter browsing through some solutions, simply disabling // ...
async submit() {
const params = runInAction(() => this.serializeParams());
await saveServiceApi(params);
// ...
} But I also found some statements in the Mobx official documentation:
So in this use-case, I'm a bit puzzled about my usage of If I miss something, I'd also like to know what the recommended practice should be🤔 It would be much appreciated if someone could address my confusion👋 |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
Basically everything should be either class CounterStore {
constructor() {
this.counter = 0;
makeObservable(this, {
counter: observable,
increment: action,
submit: action, // <--
});
}
/*....*/
async submit() {
// this already runs in action, no need for extra `runInAction` before first await, but also no harm in using it
const params = this.serializeParams();
await saveServiceApi(params); // interact with server
runInAction(() => {
// In between awaits the runInAction is required. See `flow` for an alternative:
// https://mobx.js.org/actions.html#using-flow-instead-of-async--await-
})
}
} Conceptually it's related to Command Query Separation |
Beta Was this translation helpful? Give feedback.
Basically everything should be either
action
orcomputed
.computed
must be pure function, so everything else isaction
.