diff --git a/packages/yew-agent/src/hooks.rs b/packages/yew-agent/src/hooks.rs new file mode 100644 index 00000000000..5a93ee56c8a --- /dev/null +++ b/packages/yew-agent/src/hooks.rs @@ -0,0 +1,56 @@ +use std::cell::RefCell; +use std::rc::Rc; + +use crate::*; +use yew::prelude::*; + +/// State handle for [`use_bridge`] hook +pub struct UseBridgeHandle +where + T: Bridged, +{ + inner: Rc>>>, +} + +impl UseBridgeHandle +where + T: Bridged, +{ + /// Send a message to an agent. + pub fn send(&self, msg: T::Input) { + let mut bridge = self.inner.borrow_mut(); + bridge.send(msg); + } +} + +/// A hook to bridge to an Agent. +/// +/// This hooks will only bridge the agent once over the entire component lifecycle. +/// +/// Takes a callback as the only argument. The callback will be updated on every render to make +/// sure captured values (if any) are up to date. +pub fn use_bridge(on_output: F) -> UseBridgeHandle +where + T: Bridged, + F: Fn(T::Output) + 'static, +{ + let on_output = Rc::new(on_output); + + let on_output_clone = on_output.clone(); + let on_output_ref = use_ref(move || on_output_clone); + + // Refresh the callback on every render. + { + let mut on_output_ref = on_output_ref.borrow_mut(); + *on_output_ref = on_output; + } + + let bridge = use_ref(move || { + T::bridge(Callback::from(move |output| { + let on_output = on_output_ref.borrow().clone(); + on_output(output); + })) + }); + + UseBridgeHandle { inner: bridge } +} diff --git a/packages/yew-agent/src/lib.rs b/packages/yew-agent/src/lib.rs index 90fba65e566..17232e63e23 100644 --- a/packages/yew-agent/src/lib.rs +++ b/packages/yew-agent/src/lib.rs @@ -1,11 +1,13 @@ //! This module contains types to support multi-threading and state management. +mod hooks; mod link; mod local; mod pool; pub mod utils; mod worker; +pub use hooks::{use_bridge, UseBridgeHandle}; pub use link::AgentLink; pub(crate) use link::*; pub use local::{Context, Job}; diff --git a/website/docs/concepts/agents.md b/website/docs/concepts/agents.md index 637096d84f7..db1e877d837 100644 --- a/website/docs/concepts/agents.md +++ b/website/docs/concepts/agents.md @@ -36,6 +36,8 @@ In order for agents to run concurrently, Yew uses [web-workers](https://develope A bridge allows bi-directional communication between an agent and a component. Bridges also allow agents to communicate with one another. +A `use_bridge` hook is also provided to create bridges in a function component. + ### Dispatchers A dispatcher allows uni-directional communication between a component and an agent. A dispatcher allows a component to send messages to an agent.