diff --git a/packages/core/src/global_context.rs b/packages/core/src/global_context.rs index d5a64ffc8..6851e415d 100644 --- a/packages/core/src/global_context.rs +++ b/packages/core/src/global_context.rs @@ -30,12 +30,22 @@ pub fn throw_error(error: impl Into + 'static) { Runtime::with(|rt| rt.throw_error(rt.current_scope_id(), error)) } -/// Consume context from the current scope +/// Try to consume context from the current scope, returning `None` if not found. +/// +/// Unlike `use_context`, this is **not** a hook. It reads the context value directly from the +/// runtime each time it is called, rather than caching it on first render. This means it can be +/// called from anywhere the Dioxus runtime is active — inside event handlers, async tasks, spawned +/// futures, or other non-hook contexts — without following the rules of hooks. pub fn try_consume_context() -> Option { Runtime::with_current_scope(|cx| cx.consume_context::()) } -/// Consume context from the current scope +/// Consume context from the current scope, panicking if not found. +/// +/// Unlike `use_context`, this is **not** a hook. It reads the context value directly from the +/// runtime each time it is called, rather than caching it on first render. This means it can be +/// called from anywhere the Dioxus runtime is active — inside event handlers, async tasks, spawned +/// futures, or other non-hook contexts — without following the rules of hooks. pub fn consume_context() -> T { Runtime::with_current_scope(|cx| cx.consume_context::()) .unwrap_or_else(|| panic!("Could not find context {}", std::any::type_name::())) diff --git a/packages/hooks/src/use_context.rs b/packages/hooks/src/use_context.rs index b0190de19..305fffc66 100644 --- a/packages/hooks/src/use_context.rs +++ b/packages/hooks/src/use_context.rs @@ -1,8 +1,14 @@ use dioxus_core::{consume_context, provide_context, try_consume_context, use_hook}; -/// Consume some context in the tree, providing a sharable handle to the value +/// Try to consume some context in the tree, returning `None` if it is not found. /// -/// Does not regenerate the value if the value is changed at the parent. +/// This is a **hook** — the context value is captured once on the first render and cached +/// for the lifetime of the component. It follows the [rules of hooks](https://dioxuslabs.com/learn/essentials/state/#rules-of-hooks), +/// meaning it must be called unconditionally at the top level of a component. +/// +/// If you need to read context from outside a component body (e.g., inside an event handler, +/// async task, or spawned future), use [`try_consume_context`] instead, +/// which can be called anywhere the Dioxus runtime is active. #[doc = include_str!("../docs/rules_of_hooks.md")] #[doc = include_str!("../docs/moving_state_around.md")] #[must_use] @@ -10,9 +16,16 @@ pub fn try_use_context() -> Option { use_hook(|| try_consume_context::()) } -/// Consume some context in the tree, providing a sharable handle to the value +/// Consume some context in the tree, panicking if it is not found. +/// +/// This is a **hook** — the context value is captured once on the first render and cached +/// for the lifetime of the component. It follows the [rules of hooks](https://dioxuslabs.com/learn/essentials/state/#rules-of-hooks), +/// meaning it must be called unconditionally at the top level of a component. +/// +/// If you need to read context from outside a component body (e.g., inside an event handler, +/// async task, or spawned future), use [`consume_context`] instead, +/// which can be called anywhere the Dioxus runtime is active. /// -/// Does not regenerate the value if the value is changed at the parent. /// ```rust /// # use dioxus::prelude::*; /// # #[derive(Clone, Copy, PartialEq, Debug)]