MobXGlobals.runId is not associated with actual run
Hey,
Looks like nested deriviations override runId without restoring it later, so the runId cannot be used to identify the run. Is it intended?
How to reproduce the issue:
class Store {
get foo() {
console.log('foo', _getGlobalState().runId);
return 'foo';
}
get bar() {
console.log('bar', _getGlobalState().runId);
const foo = this.foo;
console.log('bar', _getGlobalState().runId);
return foo + 'bar';
}
constructor() {
makeAutoObservable(this);
}
}
const store = new Store();
autorun(() => {
console.log('autorun', _getGlobalState().runId);
console.log(store.bar);
console.log('autorun', _getGlobalState().runId);
});
Intended outcome:
autorun 1
bar 2
foo 3
bar 2
foobar
autorun 1
Actual outcome:
autorun 1
bar 2
foo 3
bar 3 // here we see the foo's runId when in fact we're in the same run of bar getter
foobar
autorun 3
Versions
at least the latest one If you are unable to use CodeSandbox for whatever reasons, please list here all relevant dependencies
If you encounter the issue after upgrading from MobX 4/5 to MobX 6, make sure you've applied the migration guide: https://mobx.js.org/migrating-from-4-or-5.html -->
The relevant runId is captured in the derivations internal local state: https://github.com/mobxjs/mobx/blob/761a8dd4a658180fa5af546a155df994e78496bc/packages/mobx/src/core/derivation.ts#L177. Please note that _getGlobalState() is an internal API that you're not supposed to use directly.
Isn't it exported to let developers develop new libraries? Is there any other way for the 3rd party function to detect if it has been called during the same run?
Only within our own eco system. What are you trying to achieve?
On Thu, Jul 17, 2025, 15:03 Andres Kovalev @.***> wrote:
andres-kovalev left a comment (mobxjs/mobx#4570) https://github.com/mobxjs/mobx/issues/4570#issuecomment-3083996171
Isn't it exported to let developers develop new libraries? Is there any other way for the 3rd party function to detect if it has been called during the same run?
— Reply to this email directly, view it on GitHub https://github.com/mobxjs/mobx/issues/4570#issuecomment-3083996171, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAN4NBFJASIYBC77NXSGSUD3I6NJTAVCNFSM6AAAAACBXXMZG6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTAOBTHE4TMMJXGE . You are receiving this because you commented.Message ID: @.***>
I work on a tool that allow me to use asynchronous calls in MobX computeds, something similar to fromPromise(), but with caching across re-runs:
public userId: number;
get userName() {
const userData = sync(getUserData());
if (userData.status === 'fulfilled') return userData.data.name;
return 'loading...';
}
But to make sync() utility work correctly with cache I need to know if it's invoked during the same computed execution or re-execution. I understand it looks like a very special case. The only workaround I have at the moment is to patch global state and track trackingDeriviation change.
You could leverage https://github.com/mobxjs/mobx-utils?tab=readme-ov-file#frompromise and store the returned observable somewhere?
Yes, I know about this one, but it requires me to create more observables than I need an do it my hand. For instance, if I already have a flow with more than 1 step:
async function flow(arg1, arg2) {
const intermediate = await step1(arg);
const result = await step2(intermediate, arg2);
return result;
}
I would need to create something like:
class Store {
arg1 = undefined;
arg2 = undefined;
private get step1Promise() { return step1(this.arg1); }
get step1() { return fromPromise(this.step1Promise); }
private get step2Promise().{ return step2(this.step1.value, arg2); }
get step2() { return fromPromise(this.step2Promise); }
}
The library I think of is designed to provide an API like this one:
class Store {
arg1 = undefined;
arg2 = undefined;
get flow() {
const intermediate = sync(step1)(this.arg1);
const result = sync(step2)(intermediate, arg2);
return result;
}
(or similar)