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

Persisted state across argument changes #1165

Open
scottmessinger opened this issue Dec 13, 2024 · 1 comment
Open

Persisted state across argument changes #1165

scottmessinger opened this issue Dec 13, 2024 · 1 comment

Comments

@scottmessinger
Copy link

Hi! We're looking at upgrading from can-get-used-to-this and was wondering about the issue of persisting state across argument changes. According to the class based resource library, persisted state isn't natively supported by a function approach.

Just to make sure I understand, this means that the output will change it's identify in JS (e.g. a new object is created) when arguments change. If I'm right, that's a massive performance issue as a resource is often used to return a model which anchors the entire UI. Changing an argument would cause the entire UI to rerender. This seems like such an problematic choice, I'm assuming I must be misunderstanding it or I'm just unaware of a relatively easy and accessible solution.

Could you provide any insight on this? How can the function approach to resources return stable objects as the arguments change? If that's not possible, how are the performance implications mitigated?

Thank you!

@NullVoxPopuli
Copy link
Owner

What sort of public API are you working with?

Resources are a primitive for managing "a thing with cleanup", and anything beyond that is kind of an exercise in delaying tracked-entanglement to the user.

For example, in #1056, we go over a few ways of achieving similar results to "the old way of doing things", but in terms of the new apis.

Like, if you want to return a stable object as arguments change -- we first need to define what it means for arguments to change.

If we can pass a function, or object of getters, we can use an approach like this to achieve a stable return object:

import { use, resource } from 'ember-resources';

class MyDoubler {
    constructor(inputFn) { this.inputFn = inputFn; }
    
    get num() {
      return this.inputFn() * 2;
    }
    
    // not required, if you don't want
    destroy() {}
}

function Doubler(inputFn) {
  let state = new MyDoubler(inputFn);
  
  return resource(({ on, owner }) => {
    setOwner(state, owner);
    
    // not required if you don't want
    on.cleanup(() => state.destroy());

    return state;
  });
}

class Demo {
  @tracked something = 3;
    
  @use doubler = Doubler(() => this.something);
  
  get theValue() {
    return this.doubler.num; // 6
  }
}

at the same time, https://github.com/NullVoxPopuli/ember-modify-based-class-resource/ is also built on stable, public APIs, and has no intention of being abondoned or anything like that and provides the behavior you may be used to (with the modify hook).

For more philosophy reasons for why we don't, in general, want a modify hook, see here: #1054 (comment)

Now, something that is important is that resources aren't a hammer that we use for every nail -- resources are more of a specific screwdriver for a specific set of screws.

Many folks can get away with these sorts of stable references (like if they don't need per-arg-change-cleanup):

class MyClass {
  constructor(fooFn) {
    this.#fooFn = fooFn;
  }

  get foo() {
    return this.#fooFn();
  }
}

class Demo {
  // stable!
  myInstance = new MyClass(() => this.args.foo);
}

and if you need ownership / destruction linking, you may be interested in https://reactive.nullvoxpopuli.com/functions/link.link.html

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