Skip to content

Commit d8d11db

Browse files
authored
Boxed and mapped signals preparing for stores (#4413)
This PR contains just the breaking changes required for the upcoming store implementation. It adds two new primitives: 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 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 * map signals mutably * boxed signals * remove mutable borrow type from boxed writable * improve map mut example * restore boxed_mut helper * make boxed readable/writable types copy * Move away from the ReadOnlySignal alias in examples * automatically convert Write * Fix some tests * ReadSignal and WriteSignal * move read only signal alias * make maps copy * store prototype * implement derive macro * Handle generics in the derive macro * Make Selector boxable * derive boxed conversion * Get rid of store type * Remove hardcoded type from derive macro * selector -> store * Refactor store implementation * more vec methods * todo mvc store example * Implement Storable for HashMap * fix write * restore sorting logic in todomvc * derive readable and writable * improve todomvc store example * Result store * Option store * collect dead subscribers * fix clippy and formatting * recognize some common foreign types automatically * fix foreign stores in props * slice and array selectors * clean up store example * remove stores * writable is child owned * fix typo * fix clippy * fix doc tests
1 parent 6919f72 commit d8d11db

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+1306
-725
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ members = [
129129
"packages/playwright-tests/nested-suspense",
130130
"packages/playwright-tests/cli-optimization",
131131
"packages/playwright-tests/wasm-split-harness",
132-
"packages/playwright-tests/default-features-disabled",
132+
"packages/playwright-tests/default-features-disabled"
133133
]
134134

135135
[workspace.package]

example-projects/ecommerce-site/src/components/product_page.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ impl FromStr for Size {
3636
}
3737

3838
#[component]
39-
pub fn product_page(product_id: ReadOnlySignal<usize>) -> Element {
39+
pub fn product_page(product_id: ReadSignal<usize>) -> Element {
4040
let mut quantity = use_signal(|| 1);
4141
let mut size = use_signal(Size::default);
4242

example-projects/fullstack-hackernews/src/main.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub fn App() -> Element {
3232
}
3333

3434
#[component]
35-
fn Homepage(story: ReadOnlySignal<PreviewState>) -> Element {
35+
fn Homepage(story: ReadSignal<PreviewState>) -> Element {
3636
rsx! {
3737
document::Link { rel: "stylesheet", href: asset!("/assets/hackernews.css") }
3838
div { display: "flex", flex_direction: "row", width: "100%",
@@ -84,7 +84,7 @@ fn Stories() -> Element {
8484
}
8585

8686
#[component]
87-
fn StoryListing(story: ReadOnlySignal<i64>) -> Element {
87+
fn StoryListing(story: ReadSignal<i64>) -> Element {
8888
let story = use_server_future(move || get_story(story()))?;
8989

9090
let StoryItem {
@@ -167,7 +167,7 @@ impl Display for PreviewState {
167167
}
168168

169169
#[component]
170-
fn Preview(story: ReadOnlySignal<PreviewState>) -> Element {
170+
fn Preview(story: ReadSignal<PreviewState>) -> Element {
171171
let PreviewState {
172172
active_story: Some(id),
173173
} = story()

examples/backgrounded_futures.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ fn app() -> Element {
3636
}
3737

3838
#[component]
39-
fn Child(count: Signal<i32>) -> Element {
39+
fn Child(count: WriteSignal<i32>) -> Element {
4040
let mut early_return = use_signal(|| false);
4141

4242
let early = rsx! {

examples/bevy/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ fn app() -> Element {
7575
}
7676

7777
#[component]
78-
fn ColorControl(label: &'static str, color_str: Signal<String>) -> Element {
78+
fn ColorControl(label: &'static str, color_str: WriteSignal<String>) -> Element {
7979
rsx!(div {
8080
class: "color-control",
8181
{ label },

examples/dog_app.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ fn app() -> Element {
6060
}
6161

6262
#[component]
63-
fn BreedPic(breed: Signal<String>) -> Element {
63+
fn BreedPic(breed: WriteSignal<String>) -> Element {
6464
// This resource will restart whenever the breed changes
6565
let mut fut = use_resource(move || async move {
6666
#[derive(serde::Deserialize, Debug)]

examples/hash_fragment_state.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ impl FromStr for State {
8181
}
8282

8383
#[component]
84-
fn Home(url_hash: ReadOnlySignal<State>) -> Element {
84+
fn Home(url_hash: ReadSignal<State>) -> Element {
8585
// The initial state of the state comes from the url hash
8686
let mut state = use_signal(&*url_hash);
8787

examples/memo_chain.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ fn app() -> Element {
2828
}
2929

3030
#[component]
31-
fn Child(state: Memo<isize>, items: Memo<Vec<isize>>, depth: ReadOnlySignal<usize>) -> Element {
31+
fn Child(state: Memo<isize>, items: Memo<Vec<isize>>, depth: ReadSignal<usize>) -> Element {
3232
// These memos don't get re-computed when early returns happen
3333
let state = use_memo(move || state() + 1);
3434
let item = use_memo(move || items()[depth() - 1]);

examples/query_segment_search.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ fn Home() -> Element {
6363
}
6464
}
6565

66-
// Instead of accepting String and usize directly, we use ReadOnlySignal to make the parameters `Copy` and let us subscribe to them automatically inside the meme
66+
// Instead of accepting String and usize directly, we use ReadSignal to make the parameters `Copy` and let us subscribe to them automatically inside the meme
6767
#[component]
68-
fn Search(query: ReadOnlySignal<String>, word_count: ReadOnlySignal<usize>) -> Element {
68+
fn Search(query: ReadSignal<String>, word_count: ReadSignal<usize>) -> Element {
6969
const ITEMS: &[&str] = &[
7070
"hello",
7171
"world",

examples/router_resource.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Example: Updating components with use_resource
22
//! -----------------
33
//!
4-
//! This example shows how to use ReadOnlySignal to make props reactive
4+
//! This example shows how to use ReadSignal to make props reactive
55
//! when linking to it from the same component, when using use_resource
66
77
use dioxus::prelude::*;
@@ -25,15 +25,15 @@ fn App() -> Element {
2525
}
2626
}
2727

28-
// We use id: ReadOnlySignal<i32> instead of id: i32 to make id work with reactive hooks
29-
// Any i32 we pass in will automatically be converted into a ReadOnlySignal<i32>
28+
// We use id: ReadSignal<i32> instead of id: i32 to make id work with reactive hooks
29+
// Any i32 we pass in will automatically be converted into a ReadSignal<i32>
3030
#[component]
31-
fn Blog(id: ReadOnlySignal<i32>) -> Element {
31+
fn Blog(id: ReadSignal<i32>) -> Element {
3232
async fn future(n: i32) -> i32 {
3333
n
3434
}
3535

36-
// Because we accept ReadOnlySignal<i32> instead of i32, the resource will automatically subscribe to the id when we read it
36+
// Because we accept ReadSignal<i32> instead of i32, the resource will automatically subscribe to the id when we read it
3737
let res = use_resource(move || future(id()));
3838

3939
match res() {

0 commit comments

Comments
 (0)