From 3857cf83fdb81d6f85a1a4914245eb56c8c73bf3 Mon Sep 17 00:00:00 2001 From: Hamza Date: Tue, 11 May 2021 18:45:51 +0500 Subject: [PATCH] Update documentation for contexts --- docs/concepts/contexts.md | 77 +++++++++++++++++++ .../function-components/pre-defined-hooks.md | 39 +--------- packages/yew/src/context.rs | 3 +- website/sidebars.json | 3 +- 4 files changed, 84 insertions(+), 38 deletions(-) create mode 100644 docs/concepts/contexts.md diff --git a/docs/concepts/contexts.md b/docs/concepts/contexts.md new file mode 100644 index 00000000000..eb9ae7d71e8 --- /dev/null +++ b/docs/concepts/contexts.md @@ -0,0 +1,77 @@ +--- +title: Contexts +sidebar_label: Contexts +description: Using contexts to pass data within application +--- + +Generally data is passed down the component tree using props but that becomes tedious for values such as +user preferences, authentication information etc. Consider the following example which passes down the +theme using props: +```rust +// root +let theme = // ... +html! { + +} + +// Navbar component +html! { +
+ { "App title" }<Title> + <NavButton theme=theme>{ "Somewhere" }</NavButton> + </div> +} +``` + +Passing down data like this isn't ideal for something like a theme which needs to be available everywhere. +This is where contexts come in. + +Contexts provide a way to share data between components without passing them down explicitly as props. +They make data available to all components in the tree. + +## Using Contexts + +In order to use contexts, we need a struct which defines what data is to be passed. +For the above use-case, consider the following struct: +```rust +#[derive(Clone, Debug, PartialEq)] +struct Theme { + foreground: String, + background: String, +} +``` + +A context provider is required to consume the context. `ContextProvider<T>`, where `T` is the context struct is used as the provider. +`T` must implement `Clone` and `PartialEq`. `ContextProvider` is the component whose children will have the context available to them. +The children are re-rendered when the context changes. + +### Consuming context + +#### Struct components + +The `ComponentLink::context` method is used to consume contexts in struct components. + +##### Example + +```rust +struct ContextDemo { + link: ComponentLink<Self> +} + +impl Component for ContextDemo { + /// ... + fn view(&self) -> Html { + let theme = self.link.context::<Theme>(); + html! { + <button style=format!("background: {}; color: {};", theme.background, theme.foreground)> + { "Click me!" } + </button> + } + } +} +``` + +#### Function components + +`use_context` hook is used to consume contexts in function components. +See [docs for use_context](function-components/pre-defined-hooks.md#use_context) to learn more. diff --git a/docs/concepts/function-components/pre-defined-hooks.md b/docs/concepts/function-components/pre-defined-hooks.md index ad0222a3ad7..aefd57032a6 100644 --- a/docs/concepts/function-components/pre-defined-hooks.md +++ b/docs/concepts/function-components/pre-defined-hooks.md @@ -213,52 +213,19 @@ use_effect_with_deps( ## `use_context` -`use_context` is used for consuming contexts in function components. See the explanation and example in the following section to learn how to use it. +`use_context` is used for consuming [contexts](../contexts.md) in function components. -### Contexts -Generally data is passed down the component tree using props but that becomes tedious for values such as user preferences, authentication information etc. -Consider the following example which passes down the theme using props: -```rust -// root -let theme = // ... -html! { - <Navbar theme=theme /> -} - -// Navbar component -html! { - <div> - <Title theme=theme>{ "App title" }<Title> - <NavButton theme=theme>{ "Somewhere" }</NavButton> - </div> -} -``` - -Passing down data like this isn't ideal for something like a theme which needs to be available everywhere. This is where contexts come in. - -Contexts provide a way to share data between components without passing them down explicitly as props. -They make data available to all components in the tree. - -#### Using Contexts +### Example -In order to use contexts, we need a struct which defines what data is to be passed. -For the above use-case, consider the following struct: ```rust +/// App theme #[derive(Clone, Debug, PartialEq)] struct Theme { foreground: String, background: String, } -``` -A context provider is required to consume the context. `ContextProvider<T>`, where `T` is the context struct is used as the provider. -`T` must implement `Clone` and `PartialEq`. `ContextProvider` is the component whose children will have the context available to them. -Let's implement the aforementioned Navbar using contexts and function components with the `use_context` hook. - -##### Example - -```rust /// Main component #[function_component(App)] pub fn app() -> Html { diff --git a/packages/yew/src/context.rs b/packages/yew/src/context.rs index 7ca30606601..c1d64180dab 100644 --- a/packages/yew/src/context.rs +++ b/packages/yew/src/context.rs @@ -17,7 +17,8 @@ pub struct ContextProviderProps<T: Clone + PartialEq> { /// The context provider component. /// /// Every child (direct or indirect) of this component may access the context value. -/// Currently the only way to consume the context is using the [`use_context`] hook. +/// In order to consume contexts, [`ComponentLink::context`][Scope::context] method is used, +/// In function components the `use_context` hook is used. #[derive(Debug)] pub struct ContextProvider<T: Clone + PartialEq + 'static> { link: ComponentLink<Self>, diff --git a/website/sidebars.json b/website/sidebars.json index f8d0538ab00..0d1db86a5b2 100644 --- a/website/sidebars.json +++ b/website/sidebars.json @@ -59,7 +59,8 @@ ] }, "concepts/router", - "concepts/agents" + "concepts/agents", + "concepts/contexts" ], "Advanced topics": [ "advanced-topics/how-it-works",