diff --git a/examples/button.rs b/examples/button.rs deleted file mode 100644 index f001ed531..000000000 --- a/examples/button.rs +++ /dev/null @@ -1,18 +0,0 @@ -use dioxus::prelude::*; - -fn main() { - dioxus_desktop::launch(app); -} - -fn app(cx: Scope) -> Element { - cx.render(rsx! { - button { - onclick: |_| async move { - println!("hello, desktop!"); - tokio::time::sleep(std::time::Duration::from_secs(1)).await; - println!("goodbye, desktop!"); - }, - "hello, desktop!" - } - }) -} diff --git a/examples/compose.rs b/examples/compose.rs index 3ee6d36ae..f544b5a9c 100644 --- a/examples/compose.rs +++ b/examples/compose.rs @@ -1,7 +1,6 @@ //! This example shows how to create a popup window and send data back to the parent window. use dioxus::prelude::*; -use dioxus_desktop::use_window; use futures_util::StreamExt; fn main() { @@ -9,7 +8,6 @@ fn main() { } fn app(cx: Scope) -> Element { - let window = use_window(cx); let emails_sent = use_ref(cx, Vec::new); let tx = use_coroutine(cx, |mut rx: UnboundedReceiver| { @@ -34,7 +32,7 @@ fn app(cx: Scope) -> Element { // this returns a weak reference to the other window // Be careful not to keep a strong reference to the other window or it will never be dropped // and the window will never close. - window.new_window(dom, Default::default()); + dioxus_desktop::window().new_window(dom, Default::default()); }, "Click to compose a new email" } @@ -57,7 +55,6 @@ struct ComposeProps { fn compose(cx: Scope) -> Element { let user_input = use_state(cx, String::new); - let window = use_window(cx); cx.render(rsx! { div { @@ -66,15 +63,13 @@ fn compose(cx: Scope) -> Element { button { onclick: move |_| { cx.props.app_tx.send(user_input.get().clone()); - window.close(); + dioxus_desktop::window().close(); }, "Click to send" } input { - oninput: move |e| { - user_input.set(e.value.clone()); - }, + oninput: move |e| user_input.set(e.value.clone()), value: "{user_input}" } } diff --git a/examples/crm.rs b/examples/crm.rs index d2cd98118..189f98e5a 100644 --- a/examples/crm.rs +++ b/examples/crm.rs @@ -87,8 +87,6 @@ fn ClientAdd(cx: Scope) -> Element { let last_name = use_state(cx, String::new); let description = use_state(cx, String::new); - let navigator = use_navigator(cx); - cx.render(rsx! { h2 { "Add new Client" } @@ -103,7 +101,7 @@ fn ClientAdd(cx: Scope) -> Element { description: description.to_string(), }); - navigator.push(Route::ClientList {}); + dioxus_router::router().push(Route::ClientList {}); }, fieldset { diff --git a/examples/eval.rs b/examples/eval.rs index 54959df69..65c8acbeb 100644 --- a/examples/eval.rs +++ b/examples/eval.rs @@ -5,26 +5,21 @@ fn main() { } fn app(cx: Scope) -> Element { - let eval_provider = use_eval(cx); - - let future = use_future(cx, (), |_| { - to_owned![eval_provider]; - async move { - let eval = eval_provider( - r#" + let future = use_future(cx, (), |_| async move { + let eval = eval( + r#" dioxus.send("Hi from JS!"); let msg = await dioxus.recv(); console.log(msg); return "hello world"; "#, - ) - .unwrap(); + ) + .unwrap(); - eval.send("Hi from Rust!".into()).unwrap(); - let res = eval.recv().await.unwrap(); - println!("{:?}", eval.await); - res - } + eval.send("Hi from Rust!".into()).unwrap(); + let res = eval.recv().await.unwrap(); + println!("{:?}", eval.await); + res }); match future.value() { diff --git a/examples/login_form.rs b/examples/login_form.rs index 5ee47e4b5..d14338c3d 100644 --- a/examples/login_form.rs +++ b/examples/login_form.rs @@ -8,27 +8,25 @@ fn main() { } fn app(cx: Scope) -> Element { - let onsubmit = move |evt: FormEvent| { - cx.spawn(async move { - let resp = reqwest::Client::new() - .post("http://localhost:8080/login") - .form(&[ - ("username", &evt.values["username"]), - ("password", &evt.values["password"]), - ]) - .send() - .await; + let onsubmit = move |evt: FormEvent| async move { + let resp = reqwest::Client::new() + .post("http://localhost:8080/login") + .form(&[ + ("username", &evt.values["username"]), + ("password", &evt.values["password"]), + ]) + .send() + .await; - match resp { - // Parse data from here, such as storing a response token - Ok(_data) => println!("Login successful!"), + match resp { + // Parse data from here, such as storing a response token + Ok(_data) => println!("Login successful!"), - //Handle any errors from the fetch here - Err(_err) => { - println!("Login failed - you need a login server running on localhost:8080.") - } + //Handle any errors from the fetch here + Err(_err) => { + println!("Login failed - you need a login server running on localhost:8080.") } - }); + } }; cx.render(rsx! { diff --git a/examples/multiwindow.rs b/examples/multiwindow.rs index e2caeba80..c7ad2c603 100644 --- a/examples/multiwindow.rs +++ b/examples/multiwindow.rs @@ -5,14 +5,12 @@ fn main() { } fn app(cx: Scope) -> Element { - let window = dioxus_desktop::use_window(cx); - cx.render(rsx! { div { button { onclick: move |_| { let dom = VirtualDom::new(popup); - window.new_window(dom, Default::default()); + dioxus_desktop::window().new_window(dom, Default::default()); }, "New Window" } diff --git a/examples/overlay.rs b/examples/overlay.rs index 0afd830be..a4b9e7bfe 100644 --- a/examples/overlay.rs +++ b/examples/overlay.rs @@ -1,13 +1,11 @@ use dioxus::prelude::*; -use dioxus_desktop::{tao::dpi::PhysicalPosition, use_window, LogicalSize, WindowBuilder}; +use dioxus_desktop::{tao::dpi::PhysicalPosition, LogicalSize, WindowBuilder}; fn main() { dioxus_desktop::launch_cfg(app, make_config()); } fn app(cx: Scope) -> Element { - let window = use_window(cx); - cx.render(rsx! { div { width: "100%", @@ -19,7 +17,7 @@ fn app(cx: Scope) -> Element { width: "100%", height: "10px", background_color: "black", - onmousedown: move |_| window.drag(), + onmousedown: move |_| dioxus_desktop::window().drag(), } "This is an overlay!" diff --git a/examples/window_zoom.rs b/examples/window_zoom.rs index e45d71be2..bf0949d1f 100644 --- a/examples/window_zoom.rs +++ b/examples/window_zoom.rs @@ -1,12 +1,10 @@ use dioxus::prelude::*; -use dioxus_desktop::use_window; fn main() { dioxus_desktop::launch(app); } fn app(cx: Scope) -> Element { - let window = use_window(cx); let level = use_state(cx, || 1.0); cx.render(rsx! { @@ -16,7 +14,7 @@ fn app(cx: Scope) -> Element { oninput: |e| { if let Ok(new_zoom) = e.value.parse::() { level.set(new_zoom); - window.webview.zoom(new_zoom); + dioxus_desktop::window().webview.zoom(new_zoom); } } } diff --git a/packages/desktop/src/desktop_context.rs b/packages/desktop/src/desktop_context.rs index 897f8eba8..22f6dbf8f 100644 --- a/packages/desktop/src/desktop_context.rs +++ b/packages/desktop/src/desktop_context.rs @@ -28,6 +28,15 @@ use wry::webview::WebView; pub type ProxyType = EventLoopProxy; +/// Get an imperative handle to the current window without using a hook +/// +/// ## Panics +/// +/// This function will panic if it is called outside of the context of a Dioxus App. +pub fn window() -> DesktopContext { + dioxus_core::prelude::consume_context().unwrap() +} + /// Get an imperative handle to the current window pub fn use_window(cx: &ScopeState) -> &DesktopContext { cx.use_hook(|| cx.consume_context::()) diff --git a/packages/desktop/src/lib.rs b/packages/desktop/src/lib.rs index badbe3276..1aac7dfcb 100644 --- a/packages/desktop/src/lib.rs +++ b/packages/desktop/src/lib.rs @@ -23,7 +23,7 @@ use crate::query::QueryResult; pub use cfg::{Config, WindowCloseBehaviour}; pub use desktop_context::DesktopContext; pub use desktop_context::{ - use_window, use_wry_event_handler, DesktopService, WryEventHandler, WryEventHandlerId, + use_window, use_wry_event_handler, window, DesktopService, WryEventHandler, WryEventHandlerId, }; use desktop_context::{EventData, UserWindowEvent, WebviewQueue, WindowEventHandlers}; use dioxus_core::*; diff --git a/packages/html/src/eval.rs b/packages/html/src/eval.rs index 292de70fc..394713af6 100644 --- a/packages/html/src/eval.rs +++ b/packages/html/src/eval.rs @@ -48,6 +48,15 @@ pub fn use_eval(cx: &ScopeState) -> &EvalCreator { }) } +pub fn eval(script: &str) -> Result { + let eval_provider = dioxus_core::prelude::consume_context::>() + .expect("evaluator not provided"); + + eval_provider + .new_evaluator(script.to_string()) + .map(UseEval::new) +} + /// A wrapper around the target platform's evaluator. #[derive(Clone)] pub struct UseEval { diff --git a/packages/router/examples/simple_routes.rs b/packages/router/examples/simple_routes.rs index 3634f7df3..d7738beab 100644 --- a/packages/router/examples/simple_routes.rs +++ b/packages/router/examples/simple_routes.rs @@ -66,7 +66,6 @@ fn Route2(cx: Scope, user_id: usize) -> Element { #[component] fn Route3(cx: Scope, dynamic: String) -> Element { - let navigator = use_navigator(cx); let current_route = use_route(cx)?; let current_route_str = use_ref(cx, String::new); let parsed = Route::from_str(¤t_route_str.read()); @@ -78,9 +77,7 @@ fn Route3(cx: Scope, dynamic: String) -> Element { render! { input { - oninput: move |evt| { - *current_route_str.write() = evt.value.clone(); - }, + oninput: move |evt| *current_route_str.write() = evt.value.clone(), value: "{current_route_str.read()}" } "dynamic: {dynamic}" @@ -89,7 +86,7 @@ fn Route3(cx: Scope, dynamic: String) -> Element { "hello world link" } button { - onclick: move |_| { navigator.push("https://www.google.com"); }, + onclick: move |_| { dioxus_router::router().push("https://www.google.com"); }, "google link" } p { "Site Map" } diff --git a/packages/router/src/contexts/navigator.rs b/packages/router/src/contexts/navigator.rs index 961122c05..8c8bdd109 100644 --- a/packages/router/src/contexts/navigator.rs +++ b/packages/router/src/contexts/navigator.rs @@ -1,5 +1,19 @@ use crate::prelude::{ExternalNavigationFailure, IntoRoutable, RouterContext}; +/// Acquire the navigator without subscribing to updates. +/// +/// Can be called anywhere in the application provided a Router has been initialized. +/// +/// ## Panics +/// +/// Panics if there is no router present. +pub fn navigator() -> Navigator { + Navigator( + dioxus::core::prelude::consume_context::() + .expect("A router must be present to use navigator"), + ) +} + /// A view into the navigation state of a router. #[derive(Clone)] pub struct Navigator(pub(crate) RouterContext); diff --git a/packages/router/src/hooks/use_navigator.rs b/packages/router/src/hooks/use_navigator.rs index a05cd036f..9d367d83d 100644 --- a/packages/router/src/hooks/use_navigator.rs +++ b/packages/router/src/hooks/use_navigator.rs @@ -49,6 +49,7 @@ use crate::prelude::{Navigator, RouterContext}; /// # let _ = vdom.rebuild(); /// ``` #[must_use] +#[deprecated = "Prefer acquiring the router directly with `dioxus_router::router()`"] pub fn use_navigator(cx: &ScopeState) -> &Navigator { &*cx.use_hook(|| { let router = cx diff --git a/packages/router/src/hooks/use_router.rs b/packages/router/src/hooks/use_router.rs index 5f1f13e45..2cb628160 100644 --- a/packages/router/src/hooks/use_router.rs +++ b/packages/router/src/hooks/use_router.rs @@ -2,7 +2,7 @@ use dioxus::prelude::ScopeState; use crate::{prelude::RouterContext, utils::use_router_internal::use_router_internal}; -#[deprecated = "prefer the use_navigator or use_route functions"] +#[deprecated = "prefer the `router()` function or `use_route` functions"] #[must_use] /// A hook that provides access to information about the router. pub fn use_router(cx: &ScopeState) -> &RouterContext { @@ -10,3 +10,8 @@ pub fn use_router(cx: &ScopeState) -> &RouterContext { .as_ref() .expect("use_route must have access to a router") } + +/// Aquire the router without subscribing to updates. +pub fn router() -> RouterContext { + dioxus::core::prelude::consume_context().unwrap() +} diff --git a/packages/router/src/lib.rs b/packages/router/src/lib.rs index e871dc6c9..a1432d5b9 100644 --- a/packages/router/src/lib.rs +++ b/packages/router/src/lib.rs @@ -53,6 +53,8 @@ pub mod hooks { pub use use_navigator::*; } +pub use hooks::router; + /// A collection of useful items most applications might need. pub mod prelude { pub use crate::components::*;