Mobx-state-tree: resolveIdentifier invalidating twice

Created on 17 Jan 2018  路  7Comments  路  Source: mobxjs/mobx-state-tree

I need a pattern in which a view returns an object users can subscribe to before that entity exists in the store.

For example, something like this should work even before the real post 17 is added to the store:

<Author name={store.entity('post', 17).author.name} />

For that, I'm using a view with resolveIdentifier and if the entity is not ready yet, I return a "skeleton" object.

This approach seems to work great, except that the resolveIdentifier is firing twice when it founds the item instead of once. I don't know really why.

This is the simplest code I could come up with:
https://runkit.com/luisherranz/mst-resolve-identifier

const Post = types.model('Post')
  .props({
    id: types.identifier(types.string),
    ready: true,
    title: types.string,
  })

const UnknownPost = id => ({
  id,
  ready: false,
  title: null,
})

const Model = types.model('Model')
  .props({
    posts: types.array(Post),
  })
  .views(self => ({
    post: id => resolveIdentifier(Post, self, id) ||聽UnknownPost(id)
  }))

const model = Model.create()
unprotect(model)

model.posts.push({ id: 1, title: 'I am the post 1' })

console.log(`post 1 ready: ${model.post(1).ready}`) // Should be true: OK
console.log(`post 2 ready: ${model.post(2).ready}`) // Should be false: OK

let count = 0
mobx.autorun(() => {
  console.log(`post 3 ready: ${model.post(3).ready} (autorun executed ${count++} times)`)
})

model.posts.push({ id: 3, title: 'I am the post 3' }) // Should update autorun state to true

This code fires these logs:

"post 1 ready: true"
"post 2 ready: false"
"post 3 ready: false (autorun executed 0 times)"
"post 3 ready: false (autorun executed 1 times)" // <-- ???
"post 3 ready: true (autorun executed 2 times)"

By the way, that code is a simplification. The reason I'm using this pattern is because the Type of the entity is not known until the entity is received. It may be Post, Taxonomy, Author, etc.

not a bug

Most helpful comment

Ah nevermind, it doesn't

Apparently it is reacting twice because:

  • first it reacts to the change in the observable map that holds all references
  • second reaction is for the change to the actual array
[mobx.trace] 'Reaction@401' is invalidated due to a change in: '[email protected]?' 
App rendered: 2 times 
[mobx.trace] 'Reaction@401' is invalidated due to a change in: 'ObservableArray@413' 
App rendered: 3 times 

All 7 comments

By the way, what would be the approach to debug something like this? I tried whyRun() but nothing appeared.

I think you can do this when you use types.map, as that one can track the existince of an entry before it exists.

I'm going crazy speed through issues right now though, so I didn't read very carefully so I might have missed the actual question ;-).

I'll try to reproduce it in React, using a codesandbox 馃憤 鈽猴笍

There you go!
https://codesandbox.io/s/1ymqvpq214

Mobx is triggering invalidation twice when the array is updated.

I think the issue is that you are using an unprotected model rather than an action
Actions create a transaction, which means it will only trigger one change once all the operations inside the action are finished.

After I changed it to use a "addPost" action it renders 2 times

https://codesandbox.io/s/qkynzvoqpw

That being said, I don't get why resolveIdentifier is generating a reaction when being called...
@mweststrate shouldn't resolveIdentifier be marked as non tracking or some such to avoid this?

Ah nevermind, it doesn't

Apparently it is reacting twice because:

  • first it reacts to the change in the observable map that holds all references
  • second reaction is for the change to the actual array
[mobx.trace] 'Reaction@401' is invalidated due to a change in: '[email protected]?' 
App rendered: 2 times 
[mobx.trace] 'Reaction@401' is invalidated due to a change in: 'ObservableArray@413' 
App rendered: 3 times 
Was this page helpful?
0 / 5 - 0 ratings

Related issues

mshibl picture mshibl  路  3Comments

EricForgy picture EricForgy  路  4Comments

LukaszAmroz picture LukaszAmroz  路  3Comments

A-gambit picture A-gambit  路  3Comments

elado picture elado  路  4Comments