From 5ed0bc5abf2ff2e5894470848acdfe348c5a15fe Mon Sep 17 00:00:00 2001 From: Greg Johnston Date: Thu, 15 Dec 2022 22:36:20 -0500 Subject: [PATCH] Better docs for `provide_context` and `use_context` --- leptos_reactive/Cargo.toml | 1 + leptos_reactive/src/context.rs | 116 +++++++++++++++++---------------- 2 files changed, 61 insertions(+), 56 deletions(-) diff --git a/leptos_reactive/Cargo.toml b/leptos_reactive/Cargo.toml index 187985f64..5ec716f4d 100644 --- a/leptos_reactive/Cargo.toml +++ b/leptos_reactive/Cargo.toml @@ -33,6 +33,7 @@ cfg-if = "1.0.0" rmp-serde = "1.1.1" [dev-dependencies] +leptos = "0.0" tokio-test = "0.4" [features] diff --git a/leptos_reactive/src/context.rs b/leptos_reactive/src/context.rs index 292c471b5..076c22038 100644 --- a/leptos_reactive/src/context.rs +++ b/leptos_reactive/src/context.rs @@ -13,35 +13,37 @@ use crate::{runtime::with_runtime, Scope}; /// arguments to a function or properties of a component. /// /// ``` -/// # use leptos_reactive::*; -/// # create_scope(create_runtime(), |cx| { -/// -/// // Note: this example doesn’t use Leptos’s DOM model or component structure, -/// // so it ends up being a little silly. -/// -/// #[derive(Clone)] -/// struct SharedData { -/// name: (ReadSignal, WriteSignal) +/// use leptos::*; +/// +/// // define a newtype we'll provide as context +/// // contexts are stored by their types, so it can be useful to create +/// // a new type to avoid confusion with other `WriteSignal`s we may have +/// // all types to be shared via context should implement `Clone` +/// #[derive(Copy, Clone)] +/// struct ValueSetter(WriteSignal); +/// +/// #[component] +/// pub fn Provider(cx: Scope) -> Element { +/// let (value, set_value) = create_signal(cx, 0); +/// +/// // the newtype pattern isn't *necessary* here but is a good practice +/// // it avoids confusion with other possible future `WriteSignal` contexts +/// // and makes it easier to refer to it in ButtonD +/// provide_context(cx, ValueSetter(set_value)); +/// +/// // because is nested inside , +/// // it has access to the provided context +/// view! { cx,
} +/// } +/// +/// #[component] +/// pub fn Consumer(cx: Scope) -> Element { +/// // consume the provided context of type `ValueSetter` using `use_context` +/// // this traverses up the tree of `Scope`s and gets the nearest provided `ValueSetter` +/// let set_value = use_context::(cx).unwrap().0; +/// +/// todo!() /// } -/// -/// let my_context_obj = SharedData { name: create_signal(cx, "Greg".to_string()) }; -/// provide_context(cx, my_context_obj); -/// -/// // we can access it in this Scope -/// let shared_data = use_context::(cx).unwrap(); -/// let (name, set_name) = shared_data.name; -/// -/// // we can access it somewhere in a lower scope -/// cx.child_scope(|cx| { -/// let shared_data_lower_in_tree = use_context::(cx).unwrap(); -/// let (name, set_name) = shared_data.name; -/// set_name("Bob".to_string()); -/// }); -/// -/// // the change made in a lower scope updated the signal in the parent scope -/// assert_eq!(name(), "Bob"); -/// -/// # }).dispose(); /// ``` pub fn provide_context(cx: Scope, value: T) where @@ -65,35 +67,37 @@ where /// arguments to a function or properties of a component. /// /// ``` -/// # use leptos_reactive::*; -/// # create_scope(create_runtime(), |cx| { -/// -/// // Note: this example doesn’t use Leptos’s DOM model or component structure, -/// // so it ends up being a little silly. -/// -/// #[derive(Clone)] -/// struct SharedData { -/// name: (ReadSignal, WriteSignal) +/// use leptos::*; +/// +/// // define a newtype we'll provide as context +/// // contexts are stored by their types, so it can be useful to create +/// // a new type to avoid confusion with other `WriteSignal`s we may have +/// // all types to be shared via context should implement `Clone` +/// #[derive(Copy, Clone)] +/// struct ValueSetter(WriteSignal); +/// +/// #[component] +/// pub fn Provider(cx: Scope) -> Element { +/// let (value, set_value) = create_signal(cx, 0); +/// +/// // the newtype pattern isn't *necessary* here but is a good practice +/// // it avoids confusion with other possible future `WriteSignal` contexts +/// // and makes it easier to refer to it in ButtonD +/// provide_context(cx, ValueSetter(set_value)); +/// +/// // because is nested inside , +/// // it has access to the provided context +/// view! { cx,
} +/// } +/// +/// #[component] +/// pub fn Consumer(cx: Scope) -> Element { +/// // consume the provided context of type `ValueSetter` using `use_context` +/// // this traverses up the tree of `Scope`s and gets the nearest provided `ValueSetter` +/// let set_value = use_context::(cx).unwrap().0; +/// +/// todo!() /// } -/// -/// let my_context_obj = SharedData { name: create_signal(cx, "Greg".to_string()) }; -/// provide_context(cx, my_context_obj); -/// -/// // we can access it in this Scope -/// let shared_data = use_context::(cx).unwrap(); -/// let (name, set_name) = shared_data.name; -/// -/// // we can access it somewhere in a lower scope -/// cx.child_scope(|cx| { -/// let shared_data_lower_in_tree = use_context::(cx).unwrap(); -/// let (name, set_name) = shared_data.name; -/// set_name("Bob".to_string()); -/// }); -/// -/// // the change made in a lower scope updated the signal in the parent scope -/// assert_eq!(name(), "Bob"); -/// -/// # }).dispose(); /// ``` pub fn use_context(cx: Scope) -> Option where