Skip to content

Identity problems with WeakMaps and overlapping collections of deeply reactive objects #15877

Open
@CosmoMyzrailGorynych

Description

@CosmoMyzrailGorynych

Describe the problem

Reactive state is cool. We need to work with it and yadayada. I'm really glad that Svelte exists and it is saving more time for me compared to frameworks I used previously. But, reactive states being based on Proxies results in the fact that every non-primitive value you put into reactive state is not === to itself from inside the reactive state.

There are several use cases where one needs to work with a clean, unproxified value:

  • WeakMaps. When logically the same object comes from different sets (arrays, Maps, Sets, as a property, etc.), you cannot use it as a key of a WeakMap to update/remove the same value from different places. And adding artificial primitive identifiers to your object defeats the purpose of the WeakMap.
  • Identifying objects in various subsets. REPL. Say, you have several subsets where if you delete an object, you must delete it from every one of it. E.g. filesAll and filesFiltered in a file browser component (and filtering is hecking expensive (it's just an example, my use case is different anyways so don't teach me $derived, duh)). Naive indexOf+splice fails, and… artificially tagging them to use with findIndex is:
    • Dumb if it is in my own codebase — why must I change my data model for the GUI framework?
    • Hacky if it is about objects coming from a 3rdparty and sometimes impossible if public values don't have something that would make objects distinguishable, and objects come from some 3rdparty method or whatnot.
  • $state.snapshot cause object prototype to be lost #15022 shows that the current tools for unproxifying are lacking.

Additional grudge: In a TypeScript project, you can't distinguish when a reactive proxy or a plain value is used. Having a generic that tags states as reactive would help to make typeguards in methods that disallow/require the use of reactive state, and just to help me lose less hairs when I bump into one of the issues above. The current $state return type makes things look deceptively easy when they are nuanced af.

Describe the proposed solution

  • Expose get_proxied_value from src/internal/client/proxy.js as $state.unwrap
  • Bring back $state.is as usage of $state.raw is not scalable; it requires writing non-obvious hacks for each individual case.
  • Describe both as last-resort tools to spook newbies looking for easy but bad solutions to some problems they might have. Both $state.unwrap and $state.is are advanced tools.

Previous relevant discussions:

Importance

would make my life easier

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions