Skip to main content

dioxus_hooks/
use_context.rs

1use dioxus_core::{consume_context, provide_context, try_consume_context, use_hook};
2
3/// Try to consume some context in the tree, returning `None` if it is not found.
4///
5/// This is a **hook** — the context value is captured once on the first render and cached
6/// for the lifetime of the component. It follows the [rules of hooks](https://dioxuslabs.com/learn/essentials/state/#rules-of-hooks),
7/// meaning it must be called unconditionally at the top level of a component.
8///
9/// If you need to read context from outside a component body (e.g., inside an event handler,
10/// async task, or spawned future), use [`try_consume_context`] instead,
11/// which can be called anywhere the Dioxus runtime is active.
12#[doc = include_str!("../docs/rules_of_hooks.md")]
13#[doc = include_str!("../docs/moving_state_around.md")]
14#[must_use]
15pub fn try_use_context<T: 'static + Clone>() -> Option<T> {
16    use_hook(|| try_consume_context::<T>())
17}
18
19/// Consume some context in the tree, panicking if it is not found.
20///
21/// This is a **hook** — the context value is captured once on the first render and cached
22/// for the lifetime of the component. It follows the [rules of hooks](https://dioxuslabs.com/learn/essentials/state/#rules-of-hooks),
23/// meaning it must be called unconditionally at the top level of a component.
24///
25/// If you need to read context from outside a component body (e.g., inside an event handler,
26/// async task, or spawned future), use [`consume_context`] instead,
27/// which can be called anywhere the Dioxus runtime is active.
28///
29/// ```rust
30/// # use dioxus::prelude::*;
31/// # #[derive(Clone, Copy, PartialEq, Debug)]
32/// # enum Theme { Dark, Light }
33/// fn Parent() -> Element {
34///     use_context_provider(|| Theme::Dark);
35///     rsx! { Child {} }
36/// }
37/// #[component]
38/// fn Child() -> Element {
39///     //gets context provided by parent element with use_context_provider
40///     let user_theme = use_context::<Theme>();
41///     rsx! { "user using dark mode: {user_theme == Theme::Dark}" }
42/// }
43/// ```
44#[doc = include_str!("../docs/rules_of_hooks.md")]
45#[doc = include_str!("../docs/moving_state_around.md")]
46#[must_use]
47pub fn use_context<T: 'static + Clone>() -> T {
48    use_hook(|| consume_context::<T>())
49}
50
51/// Provide some context via the tree and return a reference to it
52///
53/// Once the context has been provided, it is immutable. Mutations should be done via interior mutability.
54/// Context can be read by any child components of the context provider, and is a solution to prop
55/// drilling, using a context provider with a Signal inside is a good way to provide global/shared
56/// state in your app:
57/// ```rust
58/// # use dioxus::prelude::*;
59///fn app() -> Element {
60///    use_context_provider(|| Signal::new(0));
61///    rsx! { Child {} }
62///}
63/// // This component does read from the signal, so when the signal changes it will rerun
64///#[component]
65///fn Child() -> Element {
66///     let mut signal: Signal<i32> = use_context();
67///     rsx! {
68///         button { onclick: move |_| signal += 1, "increment context" }
69///         p {"{signal}"}
70///     }
71///}
72/// ```
73#[doc = include_str!("../docs/rules_of_hooks.md")]
74#[doc = include_str!("../docs/moving_state_around.md")]
75pub fn use_context_provider<T: 'static + Clone>(f: impl FnOnce() -> T) -> T {
76    use_hook(|| provide_context(f()))
77}