Skip to content

Conversation

ealmloff
Copy link
Member

@ealmloff ealmloff commented Jul 14, 2025

This PR contains just the breaking changes required for the upcoming store implementation. It adds two new primitives:

  1. Mutable mapped signals (without a different subscriber list). This lets you scope a writable value and pass it to a child component. It requires two closures to map the immutable and mutable references to the inner signal. With stores, these closures will be derived
  2. Boxed readable and writable values (ReadSignal, and WriteSignal). Any readable or writable types can be converted to a read signal or write signal with the boxed method or built in types are automatically converted into the boxed variants when passing into props

Design: Why isn't everything just ReadSignal and WriteSignal?

I still think exposing the underlying types in hooks are useful for three reasons:

  1. Boxed signals are copy which means they cannot be created on the fly unlike mapped signal. signal.map(|foo| &foo.bar) can easily be called in the middle of a loop in rsx and doesn't allocate in the current component. signal.map(|foo| &foo.bar).boxed() should only be called in hooks because it allocates the box in the scope
  2. Different types have different methods. The Resource type implements Readable, but it also has additional methods like restart that can be used to control the running future
  3. Most state is local and avoiding the box is better for performance and backtraces. It also lets us more easily specialize the documentation of methods for each readable/writable type

TODO:

  • Make Readable and Writable dyn compatible. Most of the complex logic is split out into extension traits which makes this PR breaking
  • Implement map_mut. This requires two different closures to map the immutable and mutable borrows since closures cannot be generic over mutability
  • Make BoxedReadable Copy
  • Merge ReadOnlySignal and BoxedReadable (and keep ReadOnlySignal as a type alias)

Closes #3610

@ealmloff ealmloff added this to the 0.8.0 milestone Jul 14, 2025
@ealmloff ealmloff added signals Related to the signals crate breaking This is a breaking change labels Jul 14, 2025
@ealmloff ealmloff changed the title Boxed and mapped signals Stores, boxed and mapped signals Jul 16, 2025
@ealmloff ealmloff added the experimental May or may not be merged label Jul 16, 2025
@jkelleyrtp jkelleyrtp added check Related to the dioxus-check crate bundle blocker blocking its associated milestone blocked Blocked by another PR/Issue bug Something isn't working and removed experimental May or may not be merged signals Related to the signals crate labels Jul 25, 2025
@ealmloff ealmloff changed the title Stores, boxed and mapped signals Boxed and mapped signals preparing for stores Jul 29, 2025
@ealmloff ealmloff marked this pull request as ready for review July 29, 2025 14:40
@ealmloff ealmloff requested a review from a team as a code owner July 29, 2025 14:40
@ealmloff ealmloff modified the milestones: 0.8.0, 0.7.0 Jul 29, 2025
@jkelleyrtp jkelleyrtp merged commit d8d11db into DioxusLabs:main Jul 31, 2025
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocked Blocked by another PR/Issue blocker blocking its associated milestone breaking This is a breaking change bug Something isn't working bundle check Related to the dioxus-check crate
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add Writable::map for Signal Mapping
2 participants