Answer to the Core Question
MobX does not expose a priority flag for reaction or autorun. The only guaranteed ordering is that reactions are scheduled in the order they become stale, which is essentially the order they were created. To enforce a specific execution sequence you have two practical options:
- Chain the reactions via observables – make the “lower‑priority” reaction depend on an observable that the “higher‑priority” reaction updates only after its side‑effect completes.
- Use a custom scheduler – pass a scheduler function to
reaction() (or autorun()) that queues callbacks by a priority value.
1. Dependency‑Chain Approach
Assume two reactions, R1 (high priority) and R2 (low priority). Create an observable readyForR2 that starts as false. Inside R1, after completing its work, set readyForR2 = true. R2 watches readyForR2 in addition to the original observable. This guarantees R2 cannot run until R1 has finished.
const state = observable({ value: 0 });
const readyForR2 = observable.box(false);
reaction(() => state.value, () => {
// high‑priority logic
console.log('R1');
readyForR2.set(true); // signal R2 can run
});
reaction(() => [state.value, readyForR2.get()], () => {
if (!readyForR2.get()) return; // guard until R1 signals
console.log('R2');
});
2. Custom Scheduler Approach
MobX 6+ accepts a scheduler callback in reaction. The scheduler receives a function that should trigger the reaction. By storing callbacks in a priority queue you can control execution order.
const priorityQueue = [];
function priorityScheduler(fn) {
// assign a priority when the reaction is created
const priority = fn.priority || 0;
priorityQueue.push({ fn, priority });
// schedule microtask to run all queued callbacks in order
Promise.resolve().then(() => {
priorityQueue.sort((a, b) => a.priority - b.priority);
priorityQueue.forEach(item => item.fn());
priorityQueue.length = 0;
});
}
reaction(() => state.value, () => {
console.log('R1');
}, { scheduler: priorityScheduler }).priority = 1;
reaction(() => state.value, () => {
console.log('R2');
}, { scheduler: priorityScheduler }).priority = 2;
The custom scheduler replaces the default microtask queue, giving you full control over the order while still respecting MobX’s reactivity contract.
Confirmed Facts
- Actions batch mutations and delay reaction notifications until the action completes.
- Reactions are normally queued in the order they become stale; this is an implementation detail, not a documented priority API.
- MobX 6+ allows a custom scheduler for
reaction and autorun.
Practical Steps for Your Codebase
- Identify the reactions that must run in a specific order.
- Choose one of the two approaches above based on complexity and maintainability.
- Implement the chosen strategy and add unit tests that log reaction execution to verify order.
- Review the dependency graph to avoid unnecessary re‑runs; remove the artificial observable if it no longer serves a purpose.
What We Need From You
Do you prefer the dependency‑chain method (which keeps logic in the reaction itself) or the custom scheduler (which centralises ordering logic)? The choice will affect how you structure the rest of the system.