Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent autorun behavior between first run and subsequent runs. #3799

Open
jereklas opened this issue Nov 21, 2023 · 2 comments
Open

Inconsistent autorun behavior between first run and subsequent runs. #3799

jereklas opened this issue Nov 21, 2023 · 2 comments
Labels

Comments

@jereklas
Copy link

jereklas commented Nov 21, 2023

Intended outcome:

I would have expected autorun to behave the same on its first run or its nth run, but it appears to do something different on the first run? For the following code I would have expected the autorun to loop until the observable value it's tracking stops changing.

test("autorun", () => {
  const o = mobx.observable.box(0);
  const seen: number[] = [];

  mobx.autorun(() => {
    seen.push(o.get());
    if (o.get() < 5) o.set(o.get() + 1);
  });
  expect(seen).toStrictEqual([0, 1, 2, 3, 4, 5]); // this assertion fails as "seen" is [0]
});

Actual outcome:
The following test case is the actual behavior.

test("autorun", () => {
  const o = mobx.observable.box(0);
  const seen: number[] = [];

  mobx.autorun(() => {
    seen.push(o.get());
    if (o.get() < 5) o.set(o.get() + 1);
  });
  // autorun doesn't continue to run even though a tracked observable value has changed
  expect(seen).toStrictEqual([0]); 

  // triggering the autorun again then causes it to loop (but it has "lost" the value 1)
  o.set(o.get() + 1);
  expect(seen).toStrictEqual([0, 2, 3, 4, 5]);
});

Versions
6.11.0

@mweststrate
Copy link
Member

This is working as intended; subscription happens after the body has completed. So you're subscribing only for the next change at the moment o is already 1, which is why you miss the first change. In other words, the first o.set doesn't trigger the autorun, because the autorun is not yet an observer of it.

@jereklas
Copy link
Author

jereklas commented Nov 21, 2023

If the subscribe is happening after the body has completed, then using a computed in this scenario is inconsistent from an observable.

test("mobx", () => {
  const a = mobx.observable.box(0);
  const b = mobx.computed(() => a.get());
  const seen: number[] = [];

  mobx.autorun(() => {
    seen.push(b.get());
    a.set(1);
  });

  // this fails it's actually [0,1]
  expect(seen).toEqual([0]); 
});

I would expect it to behave the same as the observable case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants