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

Provide data context methods with different equality #49

Closed
mitar opened this issue May 8, 2015 · 6 comments
Closed

Provide data context methods with different equality #49

mitar opened this issue May 8, 2015 · 6 comments

Comments

@mitar
Copy link
Member

mitar commented May 8, 2015

Currently, Blaze uses to store data context a reactive variable with default equality function:

A function of two arguments, called on the old value and the new value whenever the ReactiveVar is set. If it returns true, no set is performed. If omitted, the default equalsFunc returns true if its arguments are === and are of type number, boolean, string, undefined, or null.

This makes content being rerendered potentially unnecessarily. In fact, often just helpers are rerun and Blaze notices that there is nothing to update DOM with and does nothing, but still. More complex logic we have in components, more complicated it can get.

Currently, Blaze Components improve on the situation because there is no automatic dependency on the data context, but it is registered only when you access .data() or .currentData(). But still. Dependency is registered using the default equality.

It might be useful to provide alternative data context access methods using different equality functions:

  • referential equality (===), assuming that data context is immutable (or that you do not care if content inside objects in data contexts change, only if the whole object change)
  • EJSON.equals for structural equality

So maybe someting like .dataReferential() and .dataStructural()?

@offthegrass
Copy link
Contributor

sounds sensible

how about if you use .data() inside constructor: -> it is considered structural, and anywhere else it's referential?

@mitar
Copy link
Member Author

mitar commented May 9, 2015

I do not think that having different semantics based on where you call a function is a good API.

@offthegrass
Copy link
Contributor

could have the default behaviour as referential, and a parameter for setting as structural

.data({structural:true})

@mitar
Copy link
Member Author

mitar commented May 11, 2015

I think we should leave default behavior as it is in Blaze. Just to minimize surprises. Default Blaze behavior is the most conservative one, it means functions/methods are rerun more often, but then Blaze does not necessary really modify DOM if everything stays the same. So this is a good default. It does not introduce any errors.

@mitar
Copy link
Member Author

mitar commented May 11, 2015

In fact, because I have not seen really non-object data contexts in practice, this means that the whole Blaze behavior is more similar to React.js: rerun everything and then compare with DOM and patch it if there are changes. The issue is that React.js uses virtual DOM do make comparison, while Blaze I think compare with real DOM. And reading real DOM is a bit slower than virtual DOM.

@mitar
Copy link
Member Author

mitar commented Oct 9, 2015

I think now that we have computed fields this is not really necessary. If you need different equality you can do:

onCreated: ->
  @dataStructural = new ComputedField (=> @data()), EJSON.equals

And this is it. :-) And then you can call @dataStructural() to get data context which will trigger reactive change only when data is structurally different.

For referential equality:

onCreated: ->
  @dataReferential = new ComputedField (=> @data()), (a, b) => a is b

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

No branches or pull requests

2 participants