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

Atom onBecomeUnobserved retriggered when it changes observable map #1122

Closed
ptomask opened this issue Aug 6, 2017 · 7 comments
Closed

Atom onBecomeUnobserved retriggered when it changes observable map #1122

ptomask opened this issue Aug 6, 2017 · 7 comments
Labels

Comments

@ptomask
Copy link

ptomask commented Aug 6, 2017

Greetings. I found a possible issue with Atom. I expect following code to print out Value getting unobserved only once, but it is printed out twice. The onBecomeUnobserved handler deletes from observable map, which is tracked in @computed value getter and I think in consequence retriggers the handler, which should not happen. Reproduced here - see the console.

In practice the code should delete an item (someKey) from cache (myMap) when that item is no longer needed by anything.

class ClassA {
  myMap = observable.map({
    someKey: 'someKeyValue',
  });

  constructor() {
    this._atom = new Atom(
      'Testing atom',
      () => {
        console.log('Value getting observed.')
      },
      () => {
        console.log('Value getting unobserved.')
        this.myMap.delete('someKey') // Retriggers onUnobserved handler?
      }
    )
  }

  @computed get value() {
    this._atom.reportObserved();
    return this.myMap.get('someKey');
  }
}


const a = new ClassA();

const unobserve = autorun(() => {
  console.log(a.value);
})

setTimeout(unobserve, 1000) // Consequently displays "Value getting unobserved" twice.
@urugator
Copy link
Collaborator

urugator commented Aug 6, 2017

I've simplified the problem:

The handler is retriggered once per each observable modified inside the onUnobserved handler
If a single observable is modified more than once, handler invocation ends up in infinite recursion.
(type of the observable does not matter, observable does not have to be tracked, computed is not needed)

const Mobx = require("mobx");

class ClassA {  
  constructor() {
    this.prop1 = Mobx.observable(1); 
    this.prop2 = Mobx.observable(2);   
    this._atom = new Mobx.Atom(
      'Testing atom',
      () => {
        console.log('Value getting observed.')
      },
      () => {
        console.log('Value getting unobserved.')        
        this.prop1.set(11); // retriggers once
        this.prop2.set(22); // retriggers once again
        //this.prop1.set(111); // <-- INFINITE RECURSION
      }
    )
  }  
  get value() { // computed not needed
     // observables don't have to be tracked
    this._atom.reportObserved();    
  }
}

const a = new ClassA();
const unobserve = Mobx.autorun(() => {
  console.log(a.value);
})
setTimeout(unobserve, 1000) 

Interestingly, to reproduce the same problem we don't have to modify any observable, we can just invoke an empty action:

const Mobx = require("mobx");

class ClassA {  
  constructor() {    
    this._atom = new Mobx.Atom(
      'Testing atom',
      () => {
        console.log('Value getting observed.')
      },
      () => {
        console.log('Value getting unobserved.')              
        Mobx.runInAction(() => {}); // <-- INFINITE RECURSION
      }
    )
  }  
  get value() {
    this._atom.reportObserved();    
  }
}

const a = new ClassA();
const unobserve = Mobx.autorun(() => {
  console.log(a.value);
})
setTimeout(unobserve, 1000) 

@mweststrate
Copy link
Member

Fixed by 3.3.1

@urugator
Copy link
Collaborator

urugator commented Oct 5, 2017

@mweststrate You sure? I just tried both of my code samples with 3.3.1 and the behavior seems the same...

@mweststrate
Copy link
Member

mweststrate commented Oct 5, 2017 via email

@urugator
Copy link
Collaborator

urugator commented Oct 5, 2017

Can you point me to the relevant commit?

@mweststrate
Copy link
Member

mweststrate commented Oct 5, 2017 via email

@urugator urugator reopened this Oct 5, 2017
mweststrate added a commit that referenced this issue Feb 27, 2018
@mweststrate
Copy link
Member

Added the test case to the MobX 4 branch, and the new Atom implementation seems to have fixed it.

@mweststrate mweststrate mentioned this issue Feb 27, 2018
38 tasks
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

3 participants