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

Allow normalization of results from computed properties #2111

Closed
4 tasks done
Maaartinus opened this issue Sep 16, 2019 · 3 comments
Closed
4 tasks done

Allow normalization of results from computed properties #2111

Maaartinus opened this issue Sep 16, 2019 · 3 comments

Comments

@Maaartinus
Copy link

I have a:

  • Idea:
    • What problem would it solve for you?
      Reduced rendering.
    • Do you think others will benefit from this change as well and it should in core package (see also mobx-utils)?
      Everyone returning arrays or objects from @computed may benefit. It's no utility, just an option for @computed.
    • Are you willing to (attempt) a PR yourself?
      Not without getting a lot of help.

A simple property like

@computed
get firstTwo() : Array<Entity> {
    return this.entities.slice(0, Math.min(this.entities.length, 2))
}

gets recomputed every time any entity change and returns a new array, which is quite often equal to the previous value (this example is a big simplification of what happens in a real project). It'd be nice to have something like @computed(equals=myEquals), which would return the old value in case myEquals returns a truthy value.

This normalization is something, I can't do myself, as I have no access to the old value. An alternative could be providing some global mobx.oldComputedValue accessible during the execution of the getter body.

@danielkcz
Copy link
Contributor

danielkcz commented Sep 17, 2019

Well, you don't have immediate access to the previous value, but I believe something like this should work, right?

class {
  firstTwoMemo = []
  get firstTwo() : Array<Entity> {
    const newValue = this.entities.slice(0, Math.min(this.entities.length, 2))
    if (newValue !== this.firstTwoMemo) {
      this.firstTwoMemo = newValue
    }
    return this.firstTwoMemo
  }  
}

I suppose it might be more convenient having it in MobX, but unless you are willing to come up with PR, I think you will have to do with this solution.

@urugator
Copy link
Collaborator

urugator commented Sep 17, 2019

@computed({ equals: myEquals })

https://mobx.js.org/refguide/computed-decorator.html

Options for computed

equals: By default comparer.default. This acts as a comparison function for comparing the previous value with the next value. If this function considers the previous and next values to be equal, then observers will not be re-evaluated. This is useful when working with structural data, and types from other libraries. For example, a computed moment instance could use (a, b) => a.isSame(b)
comparer.structural comes in handy if you want to use structural comparison to determine whether the new value is different from the previous value (and as a result notify observers).

EDIT: for arrays/objects you can use @computed.struct shorthand

EDIT2: oh actually, I am not sure if decorator accepts options... but you can create standalone computed and use it from getter:

get firstTwo() {
  return this.firstTwoComputed.get();
}

@lock
Copy link

lock bot commented Nov 16, 2019

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs or questions.

@lock lock bot locked as resolved and limited conversation to collaborators Nov 16, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants