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

Add compare key to computed using accessor syntax #3245

Open
briancray opened this issue Jun 12, 2018 · 4 comments
Open

Add compare key to computed using accessor syntax #3245

briancray opened this issue Jun 12, 2018 · 4 comments

Comments

@briancray
Copy link

briancray commented Jun 12, 2018

Currently you can use computeds with get() and set() keys as the syntax. I'd love to also see a compare() key. The compare key allows you to define a custom comparator for new and old values to see whether downstream dependencies and observers should fire.

I could be wrong, but right now all non-literal computeds seem to always fire observers when their upstream values change. This change would allow me to stop non-changes to objects from trickling downstream unnecessarily.

For example:

computed: {
    myObj: {
        get() {
            const foo = this.get('mySourceObj')
            return Object.assign({}, foo)
        }
        compare: JSON.stringify,
    }
}

This would use JSON.stringify(val) === JSON.stringify(oldVal) instead of val === oldVal

@fskreuz
Copy link
Contributor

fskreuz commented Jun 12, 2018

Computeds always fire whenever its dependencies change (in this case, mySourceObj). Ractive then computes the value, caches it, and then informs the dependents about the change. The next time it does this, in addition to the above, Ractive compares the computed result with the cached result. If the value is equal, there's no change and Ractive doesn't inform dependents. Otherwise, it does. The comparison, iirc, is a ===.

In your case, however, your computed will always trigger dependents because it always returns a new object by way of an Object.assign. If the object didn't change, just don't do the Object.assign.

@briancray
Copy link
Author

Computeds always fire whenever its dependencies change (in this case, mySourceObj). Ractive then computes the value, caches it, and then informs the dependents about the change. The next time it does this, in addition to the above, Ractive compares the computed result with the cached result. If the value is equal, there's no change and Ractive doesn't inform dependents. Otherwise, it does. The comparison, iirc, is a ===.

Exactly my point. I'd like to see a way to customize the equality check so I don't unnecessarily update the downstream where === fails (non-literals). Allowing me to use JSON.stringify instead solves 99% of non-literal cases.

In your case, however, your computed will always trigger dependents because it always returns a new object by way of an Object.assign. If the object didn't change, just don't do the Object.assign.

My example was intentionally an oversimplification. I was more giving the example to show the compare syntax.

@evs-chris
Copy link
Contributor

There was an issue a while back to make ractive more immutable-friendly by allowing a strict set that just defers to strict equality checks rather than assuming any object-ish thing has changed. I think that that and this would be a relatively small/simple code change and it makes sense, especially if you use computeds extensively (I have some computeds that depend on computeds that depend on computeds).

I will say that outside of strict (usually true for the option value in other parts of the API), you'll probably be required to supply your own full comparator e.g. (a, b) => JSON.stringify(a) === JSON.stringify(b) unless the 'json' option still exists for merge, in which case it may be applied here as well.

I'll take a poke at it when I get a few spare cycles if no one else beats me to it.

@dagnelies
Copy link
Contributor

@briancray : as a workaround, you could do the compare yourself in the get() to return the cached version in case the new object is identical

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

No branches or pull requests

4 participants