diff --git a/Cargo.toml b/Cargo.toml
index b1a221805..cf4e99b42 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -29,6 +29,7 @@ split-debuginfo = "unpacked"
[dev-dependencies]
+futures = "0.3.15"
# For the tide ssr examples
# async-std = { version="1.9.0", features=["attributes"] }
# tide = { version="0.16.0" }
@@ -45,6 +46,8 @@ split-debuginfo = "unpacked"
# dioxus-webview = { path="./packages/webview", version="0.0.0" }
# dioxus-hooks = { path="./packages/hooks", version="0.0.0" }
rand = "0.8.4"
+serde = { version="1.0.126", features=["derive"] }
+surf = "2.2.0"
[workspace]
diff --git a/docs/main-concepts/02-hello.md b/docs/main-concepts/02-hello.md
index a2e9deed5..14939f05d 100644
--- a/docs/main-concepts/02-hello.md
+++ b/docs/main-concepts/02-hello.md
@@ -82,8 +82,8 @@ fn main() {
dioxus::web::start(App)
}
-fn App(ctx: Context<()>) -> VNode {
- ctx.render(rsx! {
+fn App(cx: Context<()>) -> VNode {
+ cx.render(rsx! {
div { "Hello, world!" }
})
}
@@ -108,8 +108,8 @@ fn main() {
Finally, our app. Every component in Dioxus is a function that takes in a `Context` object and returns a `VNode`.
```rust
-fn App(ctx: Context<()>) -> VNode {
- ctx.render(rsx! {
+fn App(cx: Context<()>) -> VNode {
+ cx.render(rsx! {
div { "Hello, world!" }
})
};
@@ -119,7 +119,7 @@ In React, you'll save data between renders with hooks. However, hooks rely on gl
Next, we're greeted with the `rsx!` macro. This lets us add a custom DSL for declaratively building the structure of our app. The semantics of this macro are similar to that of JSX and HTML, though with a familiar Rust-y interface. The `html!` macro is also available for writing components with a JSX/HTML syntax.
-The `rsx!` macro is lazy: it does not immediately produce elements or allocates, but rather builds a closure which can be rendered with `ctx.render`.
+The `rsx!` macro is lazy: it does not immediately produce elements or allocates, but rather builds a closure which can be rendered with `cx.render`.
Now, let's launch our app in a development server:
@@ -135,7 +135,7 @@ If we wanted to golf a bit, we can shrink our hello-world even smaller:
```rust
fn main() {
- dioxus::web::start(|ctx| ctx.render(diouxs::rsx!( div { "Hello, World!" } ))
+ dioxus::web::start(|cx| cx.render(diouxs::rsx!( div { "Hello, World!" } ))
}
```
diff --git a/docs/main-concepts/03-rsx.md b/docs/main-concepts/03-rsx.md
index c82e0802e..0b94d7e8f 100644
--- a/docs/main-concepts/03-rsx.md
+++ b/docs/main-concepts/03-rsx.md
@@ -12,8 +12,8 @@ You'll want to write RSX where you can, and in a future release we'll have a too
```rust
#[fc]
-fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
- ctx.render(html! {
+fn Example(cx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
+ cx.render(html! {
"Hello, {name}!"
"Status: {pending}!"
@@ -33,8 +33,8 @@ It's also a bit easier on the eyes 🙂.
```rust
#[fc]
-fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
- ctx.render(rsx! {
+fn Example(cx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
+ cx.render(rsx! {
div {
p {"Hello, {name}!"}
p {"Status: {pending}!"}
@@ -58,7 +58,7 @@ Commas are entirely optional, but might be useful to delineate between elements
The `render` function provides an **extremely efficient** allocator for VNodes and text, so try not to use the `format!` macro in your components. Rust's default `ToString` methods pass through the global allocator, but all text in components is allocated inside a manually-managed Bump arena.
```rust
-static Example: FC<()> = |ctx| {
+static Example: FC<()> = |cx| {
let text = "example";
@@ -67,11 +67,11 @@ static Example: FC<()> = |ctx| {
"hello"
};
- let user_name = use_read_async(ctx, USERNAME);
- let title = ctx.suspend(user_name, |user_name| rsx!{ h1 { "Welcome back, {user_name}" } });
+ let user_name = use_read_async(cx, USERNAME);
+ let title = cx.suspend(user_name, |user_name| rsx!{ h1 { "Welcome back, {user_name}" } });
- ctx.render(rsx!{
+ cx.render(rsx!{
div {
h1 { "Example" },
@@ -125,9 +125,9 @@ static Example: FC<()> = |ctx| {
// rsx! is lazy, and the underlying closures cannot have the same type
// Rendering produces the VNode type
{match rand::gen_range::(1..3) {
- 1 => rsx!(in ctx, h1 { "big" })
- 2 => rsx!(in ctx, h2 { "medium" })
- _ => rsx!(in ctx, h3 { "small" })
+ 1 => rsx!(in cx, h1 { "big" })
+ 2 => rsx!(in cx, h2 { "medium" })
+ _ => rsx!(in cx, h3 { "small" })
}}
// Optionals
@@ -138,12 +138,12 @@ static Example: FC<()> = |ctx| {
// Child nodes
// Returns &[VNode]
- {ctx.children()}
+ {cx.children()}
// Duplicating nodes
// Clones the nodes by reference, so they are literally identical
{{
- let node = rsx!(in ctx, h1{ "TopNode" });
+ let node = rsx!(in cx, h1{ "TopNode" });
(0..10).map(|_| node.clone())
}}
diff --git a/docs/platforms/04-concurrency.md b/docs/platforms/04-concurrency.md
index 589059fdf..3c27210f1 100644
--- a/docs/platforms/04-concurrency.md
+++ b/docs/platforms/04-concurrency.md
@@ -1,10 +1,11 @@
## Concurrency
-In Dioxus, VNodes are asynchronous and can their rendering can be paused at any time by awaiting a future. Hooks can combine this functionality with the Context and Subscription APIs to craft dynamic and efficient user experiences.
+
+In Dioxus, VNodes are asynchronous and can their rendering can be paused at any time by awaiting a future. Hooks can combine this functionality with the Context and Subscription APIs to craft dynamic and efficient user experiences.
```rust
-fn user_data(ctx: Context<()>) -> VNode {
+fn user_data(cx: Context<()>) -> VNode {
// Register this future as a task
- use_suspense(ctx, async {
+ use_suspense(cx, async {
// Continue on with the component as usual, waiting for data to arrive
let Profile { name, birthday, .. } = fetch_data().await;
html! {
@@ -16,4 +17,5 @@ fn user_data(ctx: Context<()>) -> VNode {
})
}
```
-Asynchronous components are powerful but can also be easy to misuse as they pause rendering for the component and its children. Refer to the concurrent guide for information on how to best use async components.
+
+Asynchronous components are powerful but can also be easy to misuse as they pause rendering for the component and its children. Refer to the concurrent guide for information on how to best use async components.
diff --git a/docs/platforms/05-liveview.md b/docs/platforms/05-liveview.md
index 4a91e471f..49fdeead5 100644
--- a/docs/platforms/05-liveview.md
+++ b/docs/platforms/05-liveview.md
@@ -1,12 +1,13 @@
## Liveview
+
With the Context, Subscription, and Asynchronous APIs, we've built Dioxus Liveview: a coupling of frontend and backend to deliver user experiences that do not require dedicated API development. Instead of building and maintaining frontend-specific API endpoints, components can directly access databases, server caches, and other services directly from the component.
These set of features are still experimental. Currently, we're still working on making these components more ergonomic
```rust
-fn live_component(ctx: &Context<()>) -> VNode {
+fn live_component(cx: &Context<()>) -> VNode {
use_live_component(
- ctx,
+ cx,
// Rendered via the client
#[cfg(target_arch = "wasm32")]
|| html! {
}
}
```
@@ -18,14 +18,14 @@ Here, the `Context` object is used to access hook state, create subscriptions, a
```rust
// A very terse component!
#[fc]
-fn Example(ctx: Context, name: String) -> VNode {
+fn Example(cx: Context, name: String) -> VNode {
html! {
"Hello {name}!"
}
}
// or
#[functional_component]
-static Example: FC = |ctx, name: String| html! {
"Hello {name}!"
};
+static Example: FC = |cx, name: String| html! {
"Hello {name}!"
};
```
The final output of components must be a tree of VNodes. We provide an html macro for using JSX-style syntax to write these, though, you could use any macro, DSL, templating engine, or the constructors directly.
diff --git a/docs/posts/01-hello-world.md b/docs/posts/01-hello-world.md
index dff2e3b0c..a8f1f261d 100644
--- a/docs/posts/01-hello-world.md
+++ b/docs/posts/01-hello-world.md
@@ -8,9 +8,9 @@ struct MyProps {
name: String
}
-fn Example(ctx: Context) -> VNode {
- ctx.render(html! {
-
diff --git a/docs/posts/03-vnode-macros.md b/docs/posts/03-vnode-macros.md
index 88fad2121..daf5c4646 100644
--- a/docs/posts/03-vnode-macros.md
+++ b/docs/posts/03-vnode-macros.md
@@ -12,8 +12,8 @@ You'll want to write RSX where you can, and in a future release we'll have a too
```rust
#[fc]
-fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
- ctx.render(html! {
+fn Example(cx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
+ cx.render(html! {
"Hello, {name}!"
"Status: {pending}!"
@@ -33,8 +33,8 @@ It's also a bit easier on the eyes 🙂.
```rust
#[fc]
-fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
- ctx.render(rsx! {
+fn Example(cx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
+ cx.render(rsx! {
div {
p {"Hello, {name}!"}
p {"Status: {pending}!"}
@@ -58,11 +58,11 @@ Commas are entirely optional, but might be useful to delineate between elements
The `render` function provides an **extremely efficient** allocator for VNodes and text, so try not to use the `format!` macro in your components. Rust's default `ToString` methods pass through the global allocator, but all text in components is allocated inside a manually-managed Bump arena.
```rust
-static Example: FC<()> = |ctx| {
+static Example: FC<()> = |cx| {
let text = "example";
- ctx.render(rsx!{
+ cx.render(rsx!{
div {
h1 { "Example" },
@@ -114,9 +114,9 @@ static Example: FC<()> = |ctx| {
// rsx! is lazy, and the underlying closures cannot have the same type
// Rendering produces the VNode type
{match rand::gen_range::(1..3) {
- 1 => rsx!(in ctx, h1 { "big" })
- 2 => rsx!(in ctx, h2 { "medium" })
- _ => rsx!(in ctx, h3 { "small" })
+ 1 => rsx!(in cx, h1 { "big" })
+ 2 => rsx!(in cx, h2 { "medium" })
+ _ => rsx!(in cx, h3 { "small" })
}}
// Optionals
@@ -127,12 +127,12 @@ static Example: FC<()> = |ctx| {
// Child nodes
// Returns &[VNode]
- {ctx.children()}
+ {cx.children()}
// Duplicating nodes
// Clones the nodes by reference, so they are literally identical
{{
- let node = rsx!(in ctx, h1{ "TopNode" });
+ let node = rsx!(in cx, h1{ "TopNode" });
(0..10).map(|_| node.clone())
}}
diff --git a/docs/posts/04-hooks.md b/docs/posts/04-hooks.md
index b2cd76f6e..edb62662a 100644
--- a/docs/posts/04-hooks.md
+++ b/docs/posts/04-hooks.md
@@ -1,17 +1,16 @@
-
```rust
-fn Example(ctx: &mut Context<()>) -> VNode {
- let service = use_combubulator(ctx);
+fn Example(cx: &mut Context<()>) -> VNode {
+ let service = use_combubulator(cx);
let Status { name, pending, count } = service.info();
- html! {
-
+ html! {
+
"Hello, {name}!"
"Status: {pending}!"
"Count {count}!"
-
+
}
}
```
diff --git a/docs/posts/05-context-api.md b/docs/posts/05-context-api.md
index a34b47f96..2c3a535da 100644
--- a/docs/posts/05-context-api.md
+++ b/docs/posts/05-context-api.md
@@ -1,47 +1,45 @@
# Context API
-
-
```rust
// Create contexts available to children
// Only one context can be associated with any given component
// This is known as "exposed state". Children can access this context,
// but will not be automatically subscribed.
-fn ContextCreate(ctx: &mut Context<()>) -> VNode {
- let context = ctx.set_context(|| CustomContext::new());
- html! { <> {ctx.children()} > }
+fn ContextCreate(cx: &mut Context<()>) -> VNode {
+ let context = cx.set_context(|| CustomContext::new());
+ html! { <> {cx.children()} > }
}
-fn ContextRead(ctx: &mut Context<()>) -> VNode {
+fn ContextRead(cx: &mut Context<()>) -> VNode {
// Panics if context is not available
- let some_ctx = ctx.get_context::();
- let text = some_ctx.select("some_selector");
+ let some_cx = cx.get_context::();
+ let text = some_cx.select("some_selector");
html! {
"{text}"
}
}
-fn Subscription(ctx: &mut Context<()>) -> VNode {
+fn Subscription(cx: &mut Context<()>) -> VNode {
// Open a "port" on the component for actions to trigger a re-evaluation
- let subscription = ctx.new_subscription();
+ let subscription = cx.new_subscription();
// A looping timer - the effect is re-called on every re-evaluation
- use_async_effect(ctx, move || async {
+ use_async_effect(cx, move || async {
timer::new(2000).await;
subscription.call();
}, None);
// A one-shot timer, the deps don't change so the effect only happens once
- use_async_effect_deps(ctx, move || async {
+ use_async_effect_deps(cx, move || async {
timer::new(2000).await;
subscription.call();
}, ());
}
// Mix subscriptions and context to make a simple Redux
-fn use_global_state(ctx: &mut Context<()>) -> T {
- let some_ctx = ctx.get_context::();
- let component_subscription = ctx.new_subscription();
- some_ctx.subscribe_component(component_subscription);
- some_ctx
+fn use_global_state(cx: &mut Context<()>) -> T {
+ let some_cx = cx.get_context::();
+ let component_subscription = cx.new_subscription();
+ some_cx.subscribe_component(component_subscription);
+ some_cx
}
```
diff --git a/docs/posts/06-subscription-api.md b/docs/posts/06-subscription-api.md
index 790266bbc..3dea9a730 100644
--- a/docs/posts/06-subscription-api.md
+++ b/docs/posts/06-subscription-api.md
@@ -1,11 +1,11 @@
-# Subscriptions
+# Subscriptions
Yew subscriptions are used to schedule update for components into the future. The `Context` object can create subscriptions:
```rust
-fn Component(ctx: Component<()>) -> VNode {
- let update = ctx.schedule();
-
+fn Component(cx: Component<()>) -> VNode {
+ let update = cx.schedule();
+
// Now, when the subscription is called, the component will be re-evaluted
update.consume();
}
@@ -13,16 +13,15 @@ fn Component(ctx: Component<()>) -> VNode {
Whenever a component's subscription is called, the component will then re-evaluated. You can consider the input properties of
a component to be just another form of subscription. By default, the Dioxus component system automatically diffs a component's props
-when the parent function is called, and if the props are different, the child component's subscription is called.
+when the parent function is called, and if the props are different, the child component's subscription is called.
The subscription API exposes this functionality allowing hooks and state management solutions the ability to update components whenever
some state or event occurs outside of the component. For instance, the `use_context` hook uses this to subscribe components that use a
particular context.
-
```rust
-fn use_context(ctx: Context) -> I {
-
+fn use_context(cx: Context) -> I {
+
}
@@ -32,6 +31,3 @@ fn use_context(ctx: Context) -> I {
```
-
-
-
diff --git a/docs/posts/10-concurrent-mode.md b/docs/posts/10-concurrent-mode.md
index 5154f04d8..990535704 100644
--- a/docs/posts/10-concurrent-mode.md
+++ b/docs/posts/10-concurrent-mode.md
@@ -5,14 +5,15 @@ Concurrent mode provides a mechanism for building efficient asynchronous compone
To make a component asynchronous, simply change its function signature to async.
```rust
-fn Example(ctx: Context<()>) -> Vnode {
+fn Example(cx: Context<()>) -> Vnode {
rsx!{
}
}
```
@@ -20,7 +21,7 @@ async fn Example(ctx: Context<()>) -> Vnode {
Now, logic in components can be awaited to delay updates of the component and its children. Like so:
```rust
-async fn Example(ctx: Context<()>) -> Vnode {
+async fn Example(cx: Context<()>) -> Vnode {
let name = fetch_name().await;
rsx!{
"Hello {name}"
}
}
@@ -30,7 +31,7 @@ async fetch_name() -> String {
}
```
-This component will only schedule its render once the fetch is complete. However, we *don't* recommend using async/await directly in your components.
+This component will only schedule its render once the fetch is complete. However, we _don't_ recommend using async/await directly in your components.
Async is a notoriously challenging yet rewarding tool for efficient tools. If not careful, locking and unlocking shared aspects of the component's context can lead to data races and panics. If a shared resource is locked while the component is awaiting, then other components can be locked or panic when trying to access the same resource. These rules are especially important when references to shared global state are accessed using the context object's lifetime. If mutable references to data captured immutably by the context are taken, then the component will panic, and cause confusion.
@@ -39,7 +40,7 @@ Instead, we suggest using hooks and future combinators that can safely utilize t
As part of our Dioxus hooks crate, we provide a data loader hook which pauses a component until its async dependencies are ready. This caches requests, reruns the fetch if dependencies have changed, and provides the option to render something else while the component is loading.
```rust
-async fn ExampleLoader(ctx: Context<()>) -> Vnode {
+async fn ExampleLoader(cx: Context<()>) -> Vnode {
/*
Fetch, pause the component from rendering at all.
@@ -49,8 +50,8 @@ async fn ExampleLoader(ctx: Context<()>) -> Vnode {
This API stores the result on the Context object, so the loaded data is taken as reference.
*/
let name: &Result = use_fetch_data("http://example.com/json", ())
- .place_holder(|ctx| rsx!{
"loading..."
})
- .delayed_place_holder(1000, |ctx| rsx!{
"still loading..."
})
+ .place_holder(|cx| rsx!{
"loading..."
})
+ .delayed_place_holder(1000, |cx| rsx!{
"still loading..."
})
.await;
match name {
@@ -60,14 +61,11 @@ async fn ExampleLoader(ctx: Context<()>) -> Vnode {
}
```
-
-
-
```rust
-async fn Example(ctx: Context<()>) -> VNode {
+async fn Example(cx: Context<()>) -> VNode {
// Diff this set between the last set
// Check if we have any outstanding tasks?
- //
+ //
// Eventually, render the component into the VDOM when the future completes
}
```
diff --git a/docs/posts/11-arena-memo.md b/docs/posts/11-arena-memo.md
index bb953ef3d..4bfb9f353 100644
--- a/docs/posts/11-arena-memo.md
+++ b/docs/posts/11-arena-memo.md
@@ -2,13 +2,13 @@
Dioxus differs slightly from other UI virtual doms in some subtle ways due to its memory allocator.
-One important aspect to understand is how props are passed down from parent components to children. All "components" (custom user-made UI elements) are tightly allocated together in an arena. However, because props and hooks are generically typed, they are casted to any and allocated on the heap - not in the arena with the components.
+One important aspect to understand is how props are passed down from parent components to children. All "components" (custom user-made UI elements) are tightly allocated together in an arena. However, because props and hooks are generically typed, they are casted to any and allocated on the heap - not in the arena with the components.
-With this system, we try to be more efficient when leaving the component arena and entering the heap. By default, props are memoized between renders using COW and context. This makes props comparisons fast - done via ptr comparisons on the cow pointer. Because memoization is done by default, parent re-renders will *not* cascade to children if the child's props did not change.
+With this system, we try to be more efficient when leaving the component arena and entering the heap. By default, props are memoized between renders using COW and context. This makes props comparisons fast - done via ptr comparisons on the cow pointer. Because memoization is done by default, parent re-renders will _not_ cascade to children if the child's props did not change.
https://dmitripavlutin.com/use-react-memo-wisely/
-This behavior is defined as an implicit attribute to user components. When in React land you might wrap a component is `react.memo`, Dioxus components are automatically memoized via an implicit attribute. You can manually configure this behavior on any component with "nomemo" to disable memoization.
+This behavior is defined as an implicit attribute to user components. When in React land you might wrap a component is `react.memo`, Dioxus components are automatically memoized via an implicit attribute. You can manually configure this behavior on any component with "nomemo" to disable memoization.
```rust
fn test() -> VNode {
@@ -21,9 +21,9 @@ fn test() -> VNode {
}
}
-static TestComponent: FC<()> = |ctx| html!{
"Hello world"
};
+static TestComponent: FC<()> = |cx| html!{
"Hello world"
};
-static TestComponent: FC<()> = |ctx| {
+static TestComponent: FC<()> = |cx| {
let g = "BLAH";
html! {
@@ -53,4 +53,4 @@ fn test(ctx: Context<()>) -> VNode {
}
```
-While the contents of the destructued bundle might change, not every child component will need to be re-rendered.
+While the contents of the destructued bundle might change, not every child component will need to be re-rendered.
diff --git a/examples/listener.rs b/examples/listener.rs
index 5db32f799..32239db0f 100644
--- a/examples/listener.rs
+++ b/examples/listener.rs
@@ -4,10 +4,10 @@ use dioxus_core::prelude::*;
fn main() {}
-static Example: FC<()> = |ctx| {
- let (name, set_name) = use_state(&ctx, || "...?");
+static Example: FC<()> = |cx| {
+ let (name, set_name) = use_state(&cx, || "...?");
- ctx.render(rsx!(
+ cx.render(rsx!(
div {
h1 { "Hello, {name}" }
// look ma - we can rsx! and html! together
@@ -17,8 +17,8 @@ static Example: FC<()> = |ctx| {
};
pub fn render<'src, 'a, F: for<'b> FnOnce(&'b NodeCtx<'src>) -> VNode<'src> + 'src + 'a, P>(
- ctx: &'a Context<'src, P>,
+ cx: &'a Context<'src, P>,
lazy_nodes: LazyNodes<'src, F>,
) -> VNode<'src> {
- ctx.render(lazy_nodes)
+ cx.render(lazy_nodes)
}
diff --git a/examples/reducer.rs b/examples/reducer.rs
index beafdfe19..a4d459057 100644
--- a/examples/reducer.rs
+++ b/examples/reducer.rs
@@ -7,12 +7,12 @@
fn main() {}
use dioxus::prelude::*;
-pub static ExampleReducer: FC<()> = |ctx| {
- let (state, reduce) = use_reducer(&ctx, PlayerState::new, PlayerState::reduce);
+pub static ExampleReducer: FC<()> = |cx| {
+ let (state, reduce) = use_reducer(&cx, PlayerState::new, PlayerState::reduce);
let is_playing = state.is_playing();
- ctx.render(rsx! {
+ cx.render(rsx! {
div {
h1 {"Select an option"}
h3 {"The radio is... {is_playing}!"}
diff --git a/examples/rsx_usage.rs b/examples/rsx_usage.rs
index 6fdfb336f..27614fc56 100644
--- a/examples/rsx_usage.rs
+++ b/examples/rsx_usage.rs
@@ -190,7 +190,7 @@ pub struct TallerProps {
}
/// This component is taller than most :)
-pub fn Taller(ctx: Context) -> VNode {
+pub fn Taller(cx: Context) -> VNode {
let b = true;
todo!()
}
diff --git a/examples/suspense.rs b/examples/suspense.rs
new file mode 100644
index 000000000..e76ccf9c5
--- /dev/null
+++ b/examples/suspense.rs
@@ -0,0 +1,52 @@
+//! Example: Suspense
+//! -----------------
+//! This example shows how the "use_fetch" hook is built on top of Dioxus' "suspense" API. Suspense enables components
+//! to wait on futures to complete before rendering the result into VNodes. These VNodes are immediately available in a
+//! "suspended" fashion and will automatically propogate to the UI when the future completes.
+//!
+//! Note that if your component updates or receives new props while it is awating the result, the future will be dropped
+//! and all work will stop. In this example, we store the future in a hook so we can always resume it.
+
+use dioxus::prelude::*;
+
+fn main() {}
+
+#[derive(serde::Deserialize)]
+struct DogApi {
+ message: String,
+}
+const ENDPOINT: &str = "https://dog.ceo/api/breeds/image/random";
+
+pub static App: FC<()> = |cx| {
+ let doggo = use_fetch(&cx, ENDPOINT, |cx, res: surf::Result| match res {
+ Ok(res) => rsx!(in cx, img { src: "{res.message}"}),
+ Err(_) => rsx!(in cx, p { "Failed to load doggo :("}),
+ });
+
+ cx.render(rsx!(
+ div {
+ h1 {"Waiting for a doggo..."}
+ {doggo}
+ }
+ ))
+};
+
+fn use_fetch<'a, T: serde::de::DeserializeOwned + 'static>(
+ cx: &impl Scoped<'a>,
+ url: &str,
+ g: impl FnOnce(dioxus_core::virtual_dom::SuspendedContext, surf::Result) -> VNode<'a> + 'a,
+) -> VNode<'a> {
+ use futures::Future;
+ use futures::FutureExt;
+ use std::pin::Pin;
+
+ // essentially we're doing a "use_effect" but with no dependent props
+ let doggo_promise: &'a mut Pin> + Send + 'static>> = cx
+ .use_hook(
+ move || surf::get(url).recv_json::().boxed(),
+ // just pass the future through
+ |p| p,
+ |_| (),
+ );
+ cx.suspend(doggo_promise, g)
+}
diff --git a/notes/SOLVEDPROBLEMS.md b/notes/SOLVEDPROBLEMS.md
index 6a00a1802..25febf0c4 100644
--- a/notes/SOLVEDPROBLEMS.md
+++ b/notes/SOLVEDPROBLEMS.md
@@ -17,7 +17,7 @@ Originally the syntax of the FC macro was meant to look like:
```rust
#[fc]
-fn example(ctx: &Context<{ name: String }>) -> VNode {
+fn example(cx: &Context<{ name: String }>) -> VNode {
html! {
}
}
```
@@ -53,7 +53,7 @@ impl FunctionProvider for SomeComponent {
pub type SomeComponent = FunctionComponent;
```
-By default, the underlying component is defined as a "functional" implementation of the `Component` trait with all the lifecycle methods. In Dioxus, we don't allow components as structs, and instead take a "hooks-only" approach. However, we still need ctx. To get these without dealing with traits, we just assume functional components are modules. This lets the macros assume an FC is a module, and `FC::Props` is its props and `FC::component` is the component. Yew's method does a similar thing, but with associated types on traits.
+By default, the underlying component is defined as a "functional" implementation of the `Component` trait with all the lifecycle methods. In Dioxus, we don't allow components as structs, and instead take a "hooks-only" approach. However, we still need cx. To get these without dealing with traits, we just assume functional components are modules. This lets the macros assume an FC is a module, and `FC::Props` is its props and `FC::component` is the component. Yew's method does a similar thing, but with associated types on traits.
Perhaps one day we might use traits instead.
@@ -71,7 +71,7 @@ mod Example {
name: String
}
- fn component(ctx: &Context) -> VNode {
+ fn component(cx: &Context) -> VNode {
html! {
}
}
```
@@ -93,7 +93,7 @@ These definitions might be ugly, but the fc macro cleans it all up. The fc macro
```rust
#[fc]
-fn example(ctx: &Context, name: String) -> VNode {
+fn example(cx: &Context, name: String) -> VNode {
html! {
}
}
}
@@ -119,19 +119,19 @@ From a certain perspective, live components are simply server-side-rendered comp
```rust
#[fc]
-static LiveFc: FC = |ctx, refresh_handler: impl FnOnce| {
+static LiveFc: FC = |cx, refresh_handler: impl FnOnce| {
// Grab the "live context"
- let live_context = ctx.use_context::();
+ let live_context = cx.use_context::();
// Ensure this component is registered as "live"
live_context.register_scope();
// send our props to the live context and get back a future
- let vnodes = live_context.request_update(ctx);
+ let vnodes = live_context.request_update(cx);
// Suspend the rendering of this component until the vnodes are finished arriving
// Render them once available
- ctx.suspend(async move {
+ cx.suspend(async move {
let output = vnodes.await;
// inject any listener handles (ie button clicks, views, etc) to the parsed nodes
@@ -153,13 +153,13 @@ Notice that LiveComponent receivers (the client-side interpretation of a LiveCom
The `VNodeTree` type is a very special type that allows VNodes to be created using a pluggable allocator. The html! macro creates something that looks like:
```rust
-static Example: FC<()> = |ctx| {
+static Example: FC<()> = |cx| {
html! {
"blah"
}
};
// expands to...
-static Example: FC<()> = |ctx| {
+static Example: FC<()> = |cx| {
// This function converts a Fn(allocator) -> VNode closure to a VNode struct that will later be evaluated.
html_macro_to_vnodetree(move |allocator| {
let mut node0 = allocator.alloc(VElement::div);
@@ -170,7 +170,7 @@ static Example: FC<()> = |ctx| {
};
```
-At runtime, the new closure is created that captures references to `ctx`. Therefore, this closure can only be evaluated while `ctx` is borrowed and in scope. However, this closure can only be evaluated with an `allocator`. Currently, the global and Bumpalo allocators are available, though in the future we will add support for creating a VDom with any allocator or arena system (IE Jemalloc, wee-alloc, etc). The intention here is to allow arena allocation of VNodes (no need to box nested VNodes). Between diffing phases, the arena will be overwritten as old nodes are replaced with new nodes. This saves allocation time and enables bump allocators.
+At runtime, the new closure is created that captures references to `cx`. Therefore, this closure can only be evaluated while `cx` is borrowed and in scope. However, this closure can only be evaluated with an `allocator`. Currently, the global and Bumpalo allocators are available, though in the future we will add support for creating a VDom with any allocator or arena system (IE Jemalloc, wee-alloc, etc). The intention here is to allow arena allocation of VNodes (no need to box nested VNodes). Between diffing phases, the arena will be overwritten as old nodes are replaced with new nodes. This saves allocation time and enables bump allocators.
## Context and lifetimes
@@ -216,8 +216,8 @@ struct ExampleContext {
items: Vec
}
-fn Example<'src>(ctx: Context<'src, ()>) -> VNode<'src> {
- let val: &'b ContextGuard = (&'b ctx).use_context(|context: &'other ExampleContext| {
+fn Example<'src>(cx: Context<'src, ()>) -> VNode<'src> {
+ let val: &'b ContextGuard = (&'b cx).use_context(|context: &'other ExampleContext| {
// always select the last element
context.items.last()
});
@@ -225,7 +225,7 @@ fn Example<'src>(ctx: Context<'src, ()>) -> VNode<'src> {
let handler1 = move |_| println!("Value is {}", val); // deref coercion performed here for printing
let handler2 = move |_| println!("Value is {}", val); // deref coercion performed here for printing
- ctx.render(html! {
+ cx.render(html! {
"Echo value with h1" "Echo value with h2"
@@ -313,9 +313,9 @@ Here's how react does it:
Any "dirty" node causes an entire subtree render. Calling "setState" at the very top will cascade all the way down. This is particularly bad for this component design:
```rust
-static APP: FC<()> = |ctx| {
+static APP: FC<()> = |cx| {
let title = use_context(Title);
- ctx.render(html!{
+ cx.render(html!{
"{title}"
// VComponent::new(|| (FC, PropsForFc)) -> needs a context to immediately update the component's props imperatively? store the props in a box on bump? store the props on the child?
@@ -334,8 +334,8 @@ static APP: FC<()> = |ctx| {
})
};
-static HEAVY_LIST: FC<()> = |ctx| {
- ctx.render({
+static HEAVY_LIST: FC<()> = |cx| {
+ cx.render({
{0.100.map(i => )}
})
};
@@ -348,7 +348,7 @@ An update to the use_context subscription will mark the node as dirty. The node
The FC layout was altered to make life easier for us inside the VirtualDom. The "view" function returns an unbounded VNode object. Calling the "view" function is unsafe under the hood, but prevents lifetimes from leaking out of the function call. Plus, it's easier to write. Because there are no lifetimes on the output (occur purely under the hood), we can escape needing to annotate them.
```rust
-fn component(ctx: Context, props: &Props) -> VNode {
+fn component(cx: Context, props: &Props) -> VNode {
}
```
@@ -378,7 +378,7 @@ struct Props {
}
-static Component: FC = |ctx| {
+static Component: FC = |cx| {
}
```
@@ -387,7 +387,7 @@ or
```rust
#[fc]
-static Component: FC = |ctx, name: &str| {
+static Component: FC = |cx, name: &str| {
}
```
@@ -406,8 +406,8 @@ enum Patch {
```
```rust
-let node_ref = use_node_ref(&ctx);
-use_effect(&ctx, || {
+let node_ref = use_node_ref(&cx);
+use_effect(&cx, || {
}, []);
div { ref: node_ref,
diff --git a/packages/atoms/README.md b/packages/atoms/README.md
index 869aa64a8..be5a5a1f6 100644
--- a/packages/atoms/README.md
+++ b/packages/atoms/README.md
@@ -53,23 +53,23 @@ This atom of state is initialized with a value of `"Green"`. The atom that is re
This is then later used in components like so:
```rust
-fn App(ctx: Context<()>) -> VNode {
+fn App(cx: Context<()>) -> VNode {
// The Atom root must be initialized at the top of the application before any use_Atom hooks
- dirac::intialize_root(&ctx, |_| {});
+ dirac::intialize_root(&cx, |_| {});
- let color = dirac::use_read(&ctx, &LightColor);
+ let color = dirac::use_read(&cx, &LightColor);
- ctx.render(rsx!( h1 {"Color of light: {color}"} ))
+ cx.render(rsx!( h1 {"Color of light: {color}"} ))
}
```
Atoms are considered "Writable" objects since any consumer may also set the Atom's value with their own:
```rust
-fn App(ctx: Context<()>) -> VNode {
- let color = dirac::use_read(&ctx, &LightColor);
- let set_color = dirac::use_write(&ctx, &LightColor);
- ctx.render(rsx!(
+fn App(cx: Context<()>) -> VNode {
+ let color = dirac::use_read(&cx, &LightColor);
+ let set_color = dirac::use_write(&cx, &LightColor);
+ cx.render(rsx!(
h1 { "Color: {color}" }
button { onclick: move |_| set_color("red"), "red" }
button { onclick: move |_| set_color("yellow"), "yellow" }
@@ -81,9 +81,9 @@ fn App(ctx: Context<()>) -> VNode {
"Reading" a value with use_read subscribes that component to any changes to that value while "Writing" a value does not. It's a good idea to use `write-only` whenever it makes sense to prevent unnecessary evaluations. Both `read` and `write` may be combined together to provide a `use_state` style hook.
```rust
-fn App(ctx: Context<()>) -> VNode {
- let (color, set_color) = dirac::use_read_write(&ctx, &Light);
- ctx.render(rsx!(
+fn App(cx: Context<()>) -> VNode {
+ let (color, set_color) = dirac::use_read_write(&cx, &Light);
+ cx.render(rsx!(
h1 { "Color: {color}" }
button { onclick: move |_| set_color("red"), "red" }
))
@@ -154,9 +154,9 @@ const CloudRatings: AtomFamily<&str, i32> = |api| {
Whenever you `select` on a `Family`, the ID of the entry is tracked. Other subscribers will only be updated if they too select the same family with the same key and that value is updated. Otherwise, these subscribers will never re-render on an "insert", "remove", or "update" of the collection. You could easily implement this yourself with Atoms, immutable datastructures, and selectors, but our implementation is more efficient and first-class.
```rust
-fn App(ctx: Context<()>) -> VNode {
- let (rating, set_rating) = dirac::use_read_write(ctx, CloudRatings.select("AWS"));
- ctx.render(rsx!(
+fn App(cx: Context<()>) -> VNode {
+ let (rating, set_rating) = dirac::use_read_write(cx, CloudRatings.select("AWS"));
+ cx.render(rsx!(
h1 { "AWS rating: {rating}" }
button { onclick: move |_| set_rating((rating + 1) % 5), "incr" }
))
diff --git a/packages/atoms/examples/api_mvc.rs b/packages/atoms/examples/api_mvc.rs
index 31e65b9ab..c473dd6e5 100644
--- a/packages/atoms/examples/api_mvc.rs
+++ b/packages/atoms/examples/api_mvc.rs
@@ -28,12 +28,12 @@ impl TitleController {
}
fn main() {
- wasm_bindgen_futures::spawn_local(dioxus_web::WebsysRenderer::start(|ctx| {
- let title = use_read(&ctx, &TITLE);
- let subtitle = use_read(&ctx, &SUBTITLE);
- let controller = TitleController::new(use_recoil_api(&ctx));
+ wasm_bindgen_futures::spawn_local(dioxus_web::WebsysRenderer::start(|cx| {
+ let title = use_read(&cx, &TITLE);
+ let subtitle = use_read(&cx, &SUBTITLE);
+ let controller = TitleController::new(use_recoil_api(&cx));
- rsx! { in ctx,
+ rsx! { in cx,
div {
"{title}"
"{subtitle}"
diff --git a/packages/atoms/examples/callback.rs b/packages/atoms/examples/callback.rs
index 78152cdbe..222e63e4d 100644
--- a/packages/atoms/examples/callback.rs
+++ b/packages/atoms/examples/callback.rs
@@ -19,11 +19,11 @@ fn update_title(api: &RecoilApi) {
}
}
-static App: FC<()> = |ctx| {
- let title = use_read(&ctx, &TITLE);
- let next_light = use_recoil_api(&ctx, |api| move |_| update_title(&api));
+static App: FC<()> = |cx| {
+ let title = use_read(&cx, &TITLE);
+ let next_light = use_recoil_api(&cx, |api| move |_| update_title(&api));
- rsx! { in ctx,
+ rsx! { in cx,
div {
"{title}"
button { onclick: {next_light}, "Next light" }
diff --git a/packages/atoms/examples/ecs.rs b/packages/atoms/examples/ecs.rs
index 1ed2a597f..f0fa9a427 100644
--- a/packages/atoms/examples/ecs.rs
+++ b/packages/atoms/examples/ecs.rs
@@ -31,13 +31,13 @@ const TODOS: EcsModel = |builder| {};
// const SELECT_TITLE: SelectorBorrowed = |s, k| TODOS.field(0).select(k);
// const SELECT_SUBTITLE: SelectorBorrowed = |s, k| TODOS.field(1).select(k);
-static App: FC<()> = |ctx| {
- use_init_recoil_root(ctx, |_| {});
+static App: FC<()> = |cx| {
+ use_init_recoil_root(cx, |_| {});
- // let title = use_recoil_value(ctx, &C_SELECTOR);
+ // let title = use_recoil_value(cx, &C_SELECTOR);
let title = "";
- rsx! { in ctx,
+ rsx! { in cx,
div {
"{title}"
// button { onclick: {next_light}, "Next light" }
diff --git a/packages/atoms/examples/family.rs b/packages/atoms/examples/family.rs
index 78eba19c0..7ac623ca6 100644
--- a/packages/atoms/examples/family.rs
+++ b/packages/atoms/examples/family.rs
@@ -13,18 +13,18 @@ struct Todo {
content: String,
}
-static App: FC<()> = |ctx| {
- use_init_recoil_root(ctx, move |cfg| {});
+static App: FC<()> = |cx| {
+ use_init_recoil_root(cx, move |cfg| {});
- let todos = use_read_family(ctx, &TODOS);
+ let todos = use_read_family(cx, &TODOS);
- // rsx! { in ctx,
+ // rsx! { in cx,
// div {
// h1 {"Basic Todolist with AtomFamilies in Recoil.rs"}
// ul { { todos.keys().map(|id| rsx! { Child { id: *id } }) } }
// }
// }
- ctx.render(html! {
+ cx.render(html! {
@@ -36,10 +36,10 @@ struct ChildProps {
id: Uuid,
}
-static Child: FC = |ctx| {
- let (todo, set_todo) = use_read_write(ctx, &TODOS.select(&ctx.id));
+static Child: FC = |cx| {
+ let (todo, set_todo) = use_read_write(cx, &TODOS.select(&cx.id));
- rsx! { in ctx,
+ rsx! { in cx,
li {
h1 {"{todo.title}"}
input { type: "checkbox", name: "scales", checked: "{todo.checked}" }
diff --git a/packages/atoms/examples/familypoc.rs b/packages/atoms/examples/familypoc.rs
index f00cfaf2f..cbec169f5 100644
--- a/packages/atoms/examples/familypoc.rs
+++ b/packages/atoms/examples/familypoc.rs
@@ -12,11 +12,11 @@ struct Todo {
contents: String,
}
-static App: FC<()> = |ctx| {
- use_init_recoil_root(ctx, |_| {});
- let todos = use_read(&ctx, &TODOS);
+static App: FC<()> = |cx| {
+ use_init_recoil_root(cx, |_| {});
+ let todos = use_read(&cx, &TODOS);
- rsx! { in ctx,
+ rsx! { in cx,
div {
"Basic Todolist with AtomFamilies in Recoil.rs"
}
@@ -28,11 +28,11 @@ struct ChildProps {
id: Uuid,
}
-static Child: FC = |ctx| {
- let todo = use_read(ctx, &TODOS).get(&ctx.id).unwrap();
- // let (todo, set_todo) = use_read_write(ctx, &TODOS);
+static Child: FC = |cx| {
+ let todo = use_read(cx, &TODOS).get(&cx.id).unwrap();
+ // let (todo, set_todo) = use_read_write(cx, &TODOS);
- rsx! { in ctx,
+ rsx! { in cx,
div {
h1 {"{todo.title}"}
input { type: "checkbox", name: "scales", checked: "{todo.checked}" }
diff --git a/packages/atoms/examples/hellorecoil.rs b/packages/atoms/examples/hellorecoil.rs
index 5b5b32a03..d9558fa24 100644
--- a/packages/atoms/examples/hellorecoil.rs
+++ b/packages/atoms/examples/hellorecoil.rs
@@ -3,12 +3,12 @@ use recoil::*;
const COUNT: Atom = |_| 0;
-static App: FC<()> = |ctx| {
- use_init_recoil_root(ctx, |_| {});
+static App: FC<()> = |cx| {
+ use_init_recoil_root(cx, |_| {});
- let (count, set_count) = use_read_write(&ctx, &COUNT);
+ let (count, set_count) = use_read_write(&cx, &COUNT);
- rsx! { in ctx,
+ rsx! { in cx,
div {
"Count: {count}"
br {}
diff --git a/packages/atoms/examples/selectorlist.rs b/packages/atoms/examples/selectorlist.rs
index d01c9326e..cc12bf06c 100644
--- a/packages/atoms/examples/selectorlist.rs
+++ b/packages/atoms/examples/selectorlist.rs
@@ -17,12 +17,12 @@ const D_SELECTOR: SelectorFamilyBorrowed = |api, key| -> &i32 {
a
};
-static App: FC<()> = |ctx| {
- use_init_recoil_root(ctx, |_| {});
+static App: FC<()> = |cx| {
+ use_init_recoil_root(cx, |_| {});
- let title = use_read(ctx, &C_SELECTOR);
+ let title = use_read(cx, &C_SELECTOR);
- rsx! { in ctx,
+ rsx! { in cx,
div {
"{title}"
// button { onclick: {next_light}, "Next light" }
diff --git a/packages/atoms/examples/selectors.rs b/packages/atoms/examples/selectors.rs
index 29b92a70c..ab4e85e76 100644
--- a/packages/atoms/examples/selectors.rs
+++ b/packages/atoms/examples/selectors.rs
@@ -5,9 +5,9 @@ const A: Atom = |_| 0;
const B: Atom = |_| 0;
const C: Selector = |api| api.get(&A) + api.get(&B);
-static App: FC<()> = |ctx| {
- use_init_recoil_root(ctx, |_| {});
- rsx! { in ctx,
+static App: FC<()> = |cx| {
+ use_init_recoil_root(cx, |_| {});
+ rsx! { in cx,
div {
Banner {}
BtnA {}
@@ -16,14 +16,14 @@ static App: FC<()> = |ctx| {
}
};
-static Banner: FC<()> = |ctx| {
- let count = use_read(&ctx, &C);
- ctx.render(rsx! { h1 { "Count: {count}" } })
+static Banner: FC<()> = |cx| {
+ let count = use_read(&cx, &C);
+ cx.render(rsx! { h1 { "Count: {count}" } })
};
-static BtnA: FC<()> = |ctx| {
- let (a, set) = use_read_write(&ctx, &A);
- rsx! { in ctx,
+static BtnA: FC<()> = |cx| {
+ let (a, set) = use_read_write(&cx, &A);
+ rsx! { in cx,
div { "a"
button { "+", onclick: move |_| set(a + 1) }
button { "-", onclick: move |_| set(a - 1) }
@@ -31,9 +31,9 @@ static BtnA: FC<()> = |ctx| {
}
};
-static BtnB: FC<()> = |ctx| {
- let (b, set) = use_read_write(&ctx, &B);
- rsx! { in ctx,
+static BtnB: FC<()> = |cx| {
+ let (b, set) = use_read_write(&cx, &B);
+ rsx! { in cx,
div { "b"
button { "+", onclick: move |_| set(b + 1) }
button { "-", onclick: move |_| set(b - 1) }
diff --git a/packages/atoms/examples/structured_app.rs b/packages/atoms/examples/structured_app.rs
index a214edc53..afbe4c615 100644
--- a/packages/atoms/examples/structured_app.rs
+++ b/packages/atoms/examples/structured_app.rs
@@ -2,7 +2,7 @@ fn main() {}
use dioxus_core::prelude::*;
-static App: FC<()> = |ctx| {
+static App: FC<()> = |cx| {
//
use_initialize_app()
};
diff --git a/packages/atoms/examples/supense_integration.rs b/packages/atoms/examples/supense_integration.rs
index cb3e6d869..f0f523ace 100644
--- a/packages/atoms/examples/supense_integration.rs
+++ b/packages/atoms/examples/supense_integration.rs
@@ -13,23 +13,23 @@ use std::future::Future;
use dioxus_core::prelude::*;
-static App: FC<()> = |ctx| {
+static App: FC<()> = |cx| {
//
let title = use_async_atom();
- let title_card = suspend(&ctx, title, move |val| {
+ let title_card = suspend(&cx, title, move |val| {
//
- rsx!(in ctx, div {
+ rsx!(in cx, div {
h3 { "{val}" }
})
});
// let fut = (use_async_atom(), use_async_atom());
- // let title_card2 = ctx.suspend(fut, move |(text, text2)| {
- // ctx.render(rsx!( h3 { "{text}" } ))
+ // let title_card2 = cx.suspend(fut, move |(text, text2)| {
+ // cx.render(rsx!( h3 { "{text}" } ))
// });
- ctx.render(rsx! {
+ cx.render(rsx! {
div {
{title_card}
// {title_card2}
diff --git a/packages/atoms/notes/Architecture.md b/packages/atoms/notes/Architecture.md
index 640b9f759..18b7b9502 100644
--- a/packages/atoms/notes/Architecture.md
+++ b/packages/atoms/notes/Architecture.md
@@ -64,7 +64,7 @@ Also, we want selectors to have internal dependencies.
## Async atoms
```rust
-let (atom, set_atom, modify_atom) = (ATOM.use_read(ctx), ATOM.use_write(ctx), ATOM.use_modify(ctx));
+let (atom, set_atom, modify_atom) = (ATOM.use_read(cx), ATOM.use_write(cx), ATOM.use_modify(cx));
const Title: AsyncAtom = |builder| {
builder.on_set(|api, new_val| async {
@@ -93,10 +93,10 @@ const ContentCards: SelectorFamily = |api, key| api.on_get_as
data
})
-static ContentCard: FC<()> = |ctx| {
- let body = async match use_recoil_value()(ctx.id).await {
- Ok(content) => rsx!{in ctx, p {"{content}"} }
- Err(e) => rsx!{in ctx, p {"Failed to load"}}
+static ContentCard: FC<()> = |cx| {
+ let body = async match use_recoil_value()(cx.id).await {
+ Ok(content) => rsx!{in cx, p {"{content}"} }
+ Err(e) => rsx!{in cx, p {"Failed to load"}}
};
rsx!{
diff --git a/packages/atoms/src/lib.rs b/packages/atoms/src/lib.rs
index 8c8aa15f6..b7a6b0f63 100644
--- a/packages/atoms/src/lib.rs
+++ b/packages/atoms/src/lib.rs
@@ -31,15 +31,15 @@ mod traits {
// Atoms, selectors, and their family variants are readable
pub trait Readable: Sized + Copy {
- fn use_read<'a, P: 'static>(self, ctx: Context<'a, P>) -> &'a T {
- hooks::use_read(&ctx, self)
+ fn use_read<'a, P: 'static>(self, cx: Context<'a, P>) -> &'a T {
+ hooks::use_read(&cx, self)
}
// This returns a future of the value
// If the atom is currently pending, that future will resolve to pending
// If the atom is currently ready, the future will immediately resolve
// if the atom switches from ready to pending, the component will re-run, returning a pending future
- fn use_read_async<'a, P>(self, ctx: Context<'a, P>) -> &'a T {
+ fn use_read_async<'a, P>(self, cx: Context<'a, P>) -> &'a T {
todo!()
}
@@ -53,11 +53,11 @@ mod traits {
// Only atoms and atom families are writable
// Selectors and selector families are not
pub trait Writable: Readable + Sized {
- fn use_read_write<'a, P>(self, ctx: Context<'a, P>) -> (&'a T, &'a Rc) {
+ fn use_read_write<'a, P>(self, cx: Context<'a, P>) -> (&'a T, &'a Rc) {
todo!()
}
- fn use_write<'a, P>(self, ctx: Context<'a, P>) -> &'a Rc {
+ fn use_write<'a, P>(self, cx: Context<'a, P>) -> &'a Rc {
todo!()
}
}
@@ -91,13 +91,13 @@ mod atoms {
use super::*;
use dioxus_core::prelude::Context;
- fn _test(ctx: Context<()>) {
+ fn _test(cx: Context<()>) {
const EXAMPLE_ATOM: Atom = |_| 10;
// ensure that atoms are both read and write
- let _ = use_read(&ctx, &EXAMPLE_ATOM);
- let _ = use_read_write(&ctx, &EXAMPLE_ATOM);
- let _ = use_write(&ctx, &EXAMPLE_ATOM);
+ let _ = use_read(&cx, &EXAMPLE_ATOM);
+ let _ = use_read_write(&cx, &EXAMPLE_ATOM);
+ let _ = use_write(&cx, &EXAMPLE_ATOM);
}
}
}
@@ -159,9 +159,9 @@ mod atomfamily {
use super::*;
const Titles: AtomHashMap = |map| {};
- fn test(ctx: Context<()>) {
- let title = Titles.select(&10).use_read(ctx);
- let t2 = use_read(&ctx, &Titles.select(&10));
+ fn test(cx: Context<()>) {
+ let title = Titles.select(&10).use_read(cx);
+ let t2 = use_read(&cx, &Titles.select(&10));
}
}
}
@@ -370,8 +370,8 @@ mod hooks {
use super::*;
use dioxus_core::{hooks::use_ref, prelude::Context, virtual_dom::Scoped};
- pub fn use_init_recoil_root
, cfg: impl Fn(())) {
+ cx.use_create_context(move || RefCell::new(RecoilRoot::new()))
}
/// Gain access to the recoil API directly - set, get, modify, everything
@@ -381,17 +381,17 @@ mod hooks {
///
/// You can use this method to create controllers that perform much more complex actions than set/get
/// However, be aware that "getting" values through this hook will not subscribe the component to any updates.
- pub fn use_recoil_api<'a>(ctx: &impl Scoped<'a>) -> &'a Rc {
- ctx.use_context::()
+ pub fn use_recoil_api<'a>(cx: &impl Scoped<'a>) -> &'a Rc {
+ cx.use_context::()
}
pub fn use_write<'a, T: AtomValue>(
- ctx: &impl Scoped<'a>,
+ cx: &impl Scoped<'a>,
// todo: this shouldn't need to be static
writable: impl Writable,
) -> &'a Rc {
- let api = use_recoil_api(ctx);
- ctx.use_hook(
+ let api = use_recoil_api(cx);
+ cx.use_hook(
move || {
let api = api.clone();
let raw_id = writable.static_id();
@@ -413,7 +413,7 @@ mod hooks {
/// This is useful if you need the memoized Atom value. However, Rc is not as easy to
/// work with as
pub fn use_read_raw<'a, T: AtomValue>(
- ctx: &impl Scoped<'a>,
+ cx: &impl Scoped<'a>,
readable: impl Readable,
) -> &'a Rc {
struct ReadHook {
@@ -421,12 +421,12 @@ mod hooks {
consumer_id: u32,
}
- let api = use_recoil_api(ctx);
- ctx.use_hook(
+ let api = use_recoil_api(cx);
+ cx.use_hook(
move || {
let mut api = api.as_ref().borrow_mut();
- let update = ctx.schedule_update();
+ let update = cx.schedule_update();
let val = api.try_get_raw(readable).unwrap();
let id = api.subscribe(readable, update);
ReadHook {
@@ -449,8 +449,8 @@ mod hooks {
}
///
- pub fn use_read<'a, T: AtomValue>(ctx: &impl Scoped<'a>, readable: impl Readable) -> &'a T {
- use_read_raw(ctx, readable).as_ref()
+ pub fn use_read<'a, T: AtomValue>(cx: &impl Scoped<'a>, readable: impl Readable) -> &'a T {
+ use_read_raw(cx, readable).as_ref()
}
/// # Use an atom in both read and write
@@ -463,16 +463,16 @@ mod hooks {
///
/// ```
/// const Title: Atom<&str> = |_| "hello";
- /// let (title, set_title) = use_read_write(ctx, &Title);
+ /// let (title, set_title) = use_read_write(cx, &Title);
///
/// // equivalent to:
- /// let (title, set_title) = (use_read(ctx, &Title), use_write(ctx, &Title));
+ /// let (title, set_title) = (use_read(cx, &Title), use_write(cx, &Title));
/// ```
pub fn use_read_write<'a, T: AtomValue + 'static>(
- ctx: &impl Scoped<'a>,
+ cx: &impl Scoped<'a>,
writable: impl Writable,
) -> (&'a T, &'a Rc) {
- (use_read(ctx, writable), use_write(ctx, writable))
+ (use_read(cx, writable), use_write(cx, writable))
}
/// # Modify an atom without using `use_read`.
@@ -491,12 +491,12 @@ mod hooks {
/// ## Example
///
/// ```ignore
- /// let modify_atom = use_modify(ctx, Atom);
+ /// let modify_atom = use_modify(cx, Atom);
///
/// modify_atom(&|a| *a += 1)
/// ```
pub fn use_modify<'a, T: AtomValue + 'static + Clone, P>(
- ctx: Context<'a, P>,
+ cx: Context<'a, P>,
writable: impl Writable,
) -> impl Fn(&dyn Fn()) {
|_| {}
@@ -506,7 +506,7 @@ mod hooks {
/// !! Any changes to the family will cause this subscriber to update
/// Try not to put this at the very top-level of your app.
pub fn use_read_family<'a, K, V, P>(
- ctx: Context<'a, P>,
+ cx: Context<'a, P>,
t: &AtomHashMap,
) -> &'a im_rc::HashMap {
todo!()
@@ -532,9 +532,9 @@ mod utils {
pub fn RecoilApp(
root: impl for<'a> Fn(Context<'a, T>) -> VNode,
) -> impl for<'a> Fn(Context<'a, T>) -> VNode {
- move |ctx| {
- use_init_recoil_root(ctx, |_| {});
- root(ctx)
+ move |cx| {
+ use_init_recoil_root(cx, |_| {});
+ root(cx)
}
}
}
diff --git a/packages/core-macro/src/fc.rs b/packages/core-macro/src/fc.rs
index ebb44005e..6d16bb8a8 100644
--- a/packages/core-macro/src/fc.rs
+++ b/packages/core-macro/src/fc.rs
@@ -133,7 +133,7 @@ impl ToTokens for FunctionComponent {
}
impl<'a> FC for #function_name<'a> {
- fn render(ctx: Context<'_>, props: function_name<'a>) -> VNode {
+ fn render(cx: Context<'_>, props: function_name<'a>) -> VNode {
let #function_name {
..
} = props;
@@ -150,12 +150,12 @@ impl ToTokens for FunctionComponent {
// name: &'a str
// }
- // pub fn component<'a>(ctx: &'a Context<'a, Props>) -> VNode<'a> {
+ // pub fn component<'a>(cx: &'a Context<'a, Props>) -> VNode<'a> {
// // Destructure the props into the parent scope
// // todo: handle expansion of lifetimes
// let Props {
// name
- // } = ctx.props;
+ // } = cx.props;
// #block
// }
diff --git a/packages/core-macro/src/htm.rs b/packages/core-macro/src/htm.rs
index 143c50cf7..00fc568c5 100644
--- a/packages/core-macro/src/htm.rs
+++ b/packages/core-macro/src/htm.rs
@@ -39,7 +39,7 @@ impl Parse for HtmlRender {
return input.parse::()?.parse::();
}
- // let ctx: Ident = s.parse()?;
+ // let cx: Ident = s.parse()?;
// s.parse::()?;
// if elements are in an array, return a bumpalo::collections::Vec rather than a Node.
let kind = if input.peek(token::Bracket) {
@@ -64,8 +64,8 @@ impl ToTokens for HtmlRender {
// create a lazy tree that accepts a bump allocator
let final_tokens = quote! {
- dioxus::prelude::LazyNodes::new(move |ctx| {
- let bump = &ctx.bump();
+ dioxus::prelude::LazyNodes::new(move |cx| {
+ let bump = &cx.bump();
#new_toks
})
@@ -152,10 +152,10 @@ struct Element {
impl ToTokens for ToToksCtx<&Element> {
fn to_tokens(&self, tokens: &mut TokenStream2) {
- // let ctx = self.ctx;
+ // let cx = self.cx;
let name = &self.inner.name.to_string();
tokens.append_all(quote! {
- dioxus::builder::ElementBuilder::new(ctx, #name)
+ dioxus::builder::ElementBuilder::new(cx, #name)
});
for attr in self.inner.attrs.iter() {
self.recurse(attr).to_tokens(tokens);
diff --git a/packages/core-macro/src/lib.rs b/packages/core-macro/src/lib.rs
index 7ef3803c9..2943f4ee2 100644
--- a/packages/core-macro/src/lib.rs
+++ b/packages/core-macro/src/lib.rs
@@ -61,8 +61,8 @@ pub fn html_template(s: TokenStream) -> TokenStream {
/// ```ignore
///
/// #[fc]
-/// fn Example(ctx: Context, name: &str) -> VNode {
-/// ctx.render(rsx! { h1 {"hello {name}"} })
+/// fn Example(cx: Context, name: &str) -> VNode {
+/// cx.render(rsx! { h1 {"hello {name}"} })
/// }
/// ```
#[proc_macro_attribute]
diff --git a/packages/core-macro/src/rsx/component.rs b/packages/core-macro/src/rsx/component.rs
index e9b42996b..068a0bb86 100644
--- a/packages/core-macro/src/rsx/component.rs
+++ b/packages/core-macro/src/rsx/component.rs
@@ -120,14 +120,14 @@ impl ToTokens for Component {
let childs = &self.children;
let children = quote! {
- ChildrenList::new(__ctx)
+ ChildrenList::new(__cx)
#( .add_child(#childs) )*
.finish()
};
tokens.append_all(quote! {
dioxus::builder::virtual_child(
- __ctx,
+ __cx,
#name,
#builder,
#key_token,
diff --git a/packages/core-macro/src/rsx/element.rs b/packages/core-macro/src/rsx/element.rs
index 23b545cb9..3827bfb9b 100644
--- a/packages/core-macro/src/rsx/element.rs
+++ b/packages/core-macro/src/rsx/element.rs
@@ -68,7 +68,7 @@ impl ToTokens for Element {
let name = &self.name.to_string();
tokens.append_all(quote! {
- dioxus::builder::ElementBuilder::new(__ctx, #name)
+ dioxus::builder::ElementBuilder::new(__cx, #name)
});
for attr in self.attrs.iter() {
@@ -221,13 +221,13 @@ impl ToTokens for ElementAttr {
}
AttrType::Event(event) => {
tokens.append_all(quote! {
- .add_listener(dioxus::events::on::#nameident(__ctx, #event))
+ .add_listener(dioxus::events::on::#nameident(__cx, #event))
});
}
AttrType::EventTokens(event) => {
//
tokens.append_all(quote! {
- .add_listener(dioxus::events::on::#nameident(__ctx, #event))
+ .add_listener(dioxus::events::on::#nameident(__cx, #event))
});
}
}
diff --git a/packages/core-macro/src/rsx/fragment.rs b/packages/core-macro/src/rsx/fragment.rs
index 840b14797..812252a25 100644
--- a/packages/core-macro/src/rsx/fragment.rs
+++ b/packages/core-macro/src/rsx/fragment.rs
@@ -50,14 +50,14 @@ impl ToTokens for Fragment {
fn to_tokens(&self, tokens: &mut TokenStream2) {
let childs = &self.children;
let children = quote! {
- ChildrenList::new(__ctx)
+ ChildrenList::new(__cx)
#( .add_child(#childs) )*
.finish()
};
tokens.append_all(quote! {
// #key_token,
dioxus::builder::vfragment(
- __ctx,
+ __cx,
None,
#children
)
diff --git a/packages/core-macro/src/rsx/mod.rs b/packages/core-macro/src/rsx/mod.rs
index 6eb6d90db..44b6584be 100644
--- a/packages/core-macro/src/rsx/mod.rs
+++ b/packages/core-macro/src/rsx/mod.rs
@@ -81,14 +81,14 @@ impl ToTokens for RsxRender {
} else {
let childs = &self.roots;
let children = quote! {
- ChildrenList::new(__ctx)
+ ChildrenList::new(__cx)
#( .add_child(#childs) )*
.finish()
};
quote! {
// #key_token,
dioxus::builder::vfragment(
- __ctx,
+ __cx,
None,
#children
)
@@ -96,17 +96,17 @@ impl ToTokens for RsxRender {
};
match &self.custom_context {
- // The `in ctx` pattern allows directly rendering
+ // The `in cx` pattern allows directly rendering
Some(ident) => out_tokens.append_all(quote! {
- #ident.render(dioxus::prelude::LazyNodes::new(move |__ctx|{
- let bump = &__ctx.bump();
+ #ident.render(dioxus::prelude::LazyNodes::new(move |__cx|{
+ let bump = &__cx.bump();
#inner
}))
}),
// Otherwise we just build the LazyNode wrapper
None => out_tokens.append_all(quote! {
- dioxus::prelude::LazyNodes::new(move |__ctx|{
- let bump = &__ctx.bump();
+ dioxus::prelude::LazyNodes::new(move |__cx|{
+ let bump = &__cx.bump();
#inner
})
}),
diff --git a/packages/core-macro/src/rsxtemplate.rs b/packages/core-macro/src/rsxtemplate.rs
index 77b399eeb..911f93e2e 100644
--- a/packages/core-macro/src/rsxtemplate.rs
+++ b/packages/core-macro/src/rsxtemplate.rs
@@ -46,7 +46,7 @@ impl Parse for RsxTemplate {
// let new_stream = TokenStream::from(t.to_s)
- // let ctx: Ident = s.parse()?;
+ // let cx: Ident = s.parse()?;
// s.parse::()?;
// if elements are in an array, return a bumpalo::collections::Vec rather than a Node.
// let kind = if s.peek(token::Bracket) {
@@ -72,8 +72,8 @@ impl ToTokens for RsxTemplate {
// // create a lazy tree that accepts a bump allocator
// let final_tokens = quote! {
- // dioxus::prelude::LazyNodes::new(move |ctx| {
- // let bump = &ctx.bump();
+ // dioxus::prelude::LazyNodes::new(move |cx| {
+ // let bump = &cx.bump();
// #new_toks
// })
diff --git a/packages/core/Cargo.toml b/packages/core/Cargo.toml
index 4fec2cafe..6263f22b4 100644
--- a/packages/core/Cargo.toml
+++ b/packages/core/Cargo.toml
@@ -40,6 +40,9 @@ serde = { version="1", features=["derive"], optional=true }
smallvec = "1.6.1"
+futures = "0.3.15"
+
+
[features]
default = []
serialize = ["serde", "generational-arena/serde"]
diff --git a/packages/core/examples/alternative.rs b/packages/core/examples/alternative.rs
index f2affa5c7..2d227dc6d 100644
--- a/packages/core/examples/alternative.rs
+++ b/packages/core/examples/alternative.rs
@@ -2,10 +2,10 @@ fn main() {}
use dioxus_core::prelude::*;
-static Example: FC<()> = |ctx| {
- ctx.render(dioxus_core::prelude::LazyNodes::new(move |ctx| {
- let bump = ctx.bump();
- dioxus_core::builder::ElementBuilder::new(ctx, "h1")
+static Example: FC<()> = |cx| {
+ cx.render(dioxus_core::prelude::LazyNodes::new(move |cx| {
+ let bump = cx.bump();
+ dioxus_core::builder::ElementBuilder::new(cx, "h1")
.children([dioxus_core::builder::text3(bump, format_args!("hello"))])
.finish()
}))
@@ -14,13 +14,13 @@ static Example: FC<()> = |ctx| {
struct Props {
text: String,
}
-static Example2: FC = |ctx| {
- ctx.render(dioxus_core::prelude::LazyNodes::new(move |__ctx| {
- let bump = __ctx.bump();
- dioxus_core::builder::ElementBuilder::new(__ctx, "h1")
+static Example2: FC = |cx| {
+ cx.render(dioxus_core::prelude::LazyNodes::new(move |__cx| {
+ let bump = __cx.bump();
+ dioxus_core::builder::ElementBuilder::new(__cx, "h1")
.children([dioxus_core::builder::text3(
bump,
- format_args!("{}", ctx.props.text),
+ format_args!("{}", cx.props.text),
)])
.finish()
}))
diff --git a/packages/core/examples/borrowed.rs b/packages/core/examples/borrowed.rs
index df57c3819..960cc217e 100644
--- a/packages/core/examples/borrowed.rs
+++ b/packages/core/examples/borrowed.rs
@@ -19,15 +19,15 @@ struct ListItem {
age: u32,
}
-fn app(ctx: Context) -> VNode {
- let (val, set_val) = use_state(&ctx, || 0);
+fn app(cx: Context) -> VNode {
+ let (val, set_val) = use_state(&cx, || 0);
- ctx.render(LazyNodes::new(move |_nodectx| {
- builder::ElementBuilder::new(_nodectx, "div")
+ cx.render(LazyNodes::new(move |_nodecx| {
+ builder::ElementBuilder::new(_nodecx, "div")
.iter_child({
- ctx.items.iter().map(|child| {
+ cx.items.iter().map(|child| {
builder::virtual_child(
- _nodectx,
+ _nodecx,
ChildItem,
ChildProps {
item: child.clone(),
@@ -38,8 +38,8 @@ fn app(ctx: Context) -> VNode {
)
})
})
- .iter_child([builder::ElementBuilder::new(_nodectx, "div")
- .iter_child([builder::text3(_nodectx.bump(), format_args!("{}", val))])
+ .iter_child([builder::ElementBuilder::new(_nodecx, "div")
+ .iter_child([builder::text3(_nodecx.bump(), format_args!("{}", val))])
.finish()])
.finish()
}))
diff --git a/packages/core/examples/contextapi.rs b/packages/core/examples/contextapi.rs
index debe9886d..1e6856ce3 100644
--- a/packages/core/examples/contextapi.rs
+++ b/packages/core/examples/contextapi.rs
@@ -13,21 +13,21 @@ struct Props {
static Example: FC = |cpt| {
todo!()
- // let value = ctx.use_context(|c: &SomeContext| c.items.last().unwrap());
+ // let value = cx.use_context(|c: &SomeContext| c.items.last().unwrap());
- // ctx.render(LazyNodes::new(move |bump| {
+ // cx.render(LazyNodes::new(move |bump| {
// builder::ElementBuilder::new(bump, "button")
// .on("click", move |_| {
- // println!("Value is {}", ctx.name);
+ // println!("Value is {}", cx.name);
// println!("Value is {}", value.as_str());
// println!("Value is {}", *value);
// })
// .on("click", move |_| {
- // println!("Value is {}", ctx.name);
+ // println!("Value is {}", cx.name);
// })
// .finish()
// }))
- // ctx.render(html! {
+ // cx.render(html! {
//
//
//
diff --git a/packages/core/examples/macrosrc.rs b/packages/core/examples/macrosrc.rs
index c40907022..b0b0977c7 100644
--- a/packages/core/examples/macrosrc.rs
+++ b/packages/core/examples/macrosrc.rs
@@ -34,7 +34,7 @@ fn main() {}
// 2: Trees are not evaluated
// */
-// let example_caller = move |ctx: &Bump| {
+// let example_caller = move |cx: &Bump| {
// todo!()
// // let p = Props { blah: true, text };
// // let c = Context { props: &p };
@@ -57,11 +57,11 @@ fn main() {}
// }
// }
-// fn component<'a>(ctx: Context<'a, Props>) -> VNode<'a> {
+// fn component<'a>(cx: Context<'a, Props>) -> VNode<'a> {
// // Write asynchronous rendering code that immediately returns a "suspended" VNode
// // The concurrent API will then progress this component when the future finishes
// // You can suspend the entire component, or just parts of it
-// let product_list = ctx.suspend(async {
+// let product_list = cx.suspend(async {
// // Suspend the rendering that completes when the future is done
// match fetch_data().await {
// Ok(data) => html! {
// "hello!"
@@ -82,27 +82,27 @@ fn main() {}
// })
// }
-// fn BuilderComp<'a>(ctx: Context<'a, Props>) -> VNode<'a> {
+// fn BuilderComp<'a>(cx: Context<'a, Props>) -> VNode<'a> {
// // VNodes can be constructed via a builder or the html! macro
// // However, both of these are "lazy" - they need to be evaluated (aka, "viewed")
// // We can "view" them with Context for ultimate speed while inside components
-// ctx.render(|bump| {
+// cx.render(|bump| {
// div(bump)
// .attr("class", "edit")
// .child(text("Hello"))
-// .child(text(ctx.ctx.text.as_ref()))
+// .child(text(cx.cx.text.as_ref()))
// .finish()
// })
// }
// #[fc]
-// fn EffcComp(ctx: Context, name: &str) -> VNode {
+// fn EffcComp(cx: Context, name: &str) -> VNode {
// // VNodes can be constructed via a builder or the html! macro
// // However, both of these are "lazy" - they need to be evaluated (aka, "viewed")
// // We can "view" them with Context for ultimate speed while inside components
// // use "phase" style allocation;
-// ctx.render(html! {
+// cx.render(html! {
//
// // your template goes here
// // feel free to directly use "name"
@@ -110,8 +110,8 @@ fn main() {}
// })
// }
-// fn FullySuspended<'a>(ctx: &'a Context) -> VNode<'a> {
-// ctx.suspend(async {
+// fn FullySuspended<'a>(cx: &'a Context) -> VNode<'a> {
+// cx.suspend(async {
// let i: i32 = 0;
// // full suspended works great with just returning VNodes!
@@ -123,7 +123,7 @@ fn main() {}
// _ => html! {
},
// };
-// if ctx.ctx.blah {
+// if cx.cx.blah {
// html! {
}
// } else {
// tex
diff --git a/packages/core/src/component.rs b/packages/core/src/component.rs
index 77ae04fc3..27975eda0 100644
--- a/packages/core/src/component.rs
+++ b/packages/core/src/component.rs
@@ -3,7 +3,7 @@
//!
//! Note - using the builder pattern does not required the Properties trait to be implemented - the only thing that matters is
//! if the type suppports PartialEq. The Properties trait is used by the rsx! and html! macros to generate the type-safe builder
-//! that ensures compile-time required and optional fields on ctx.
+//! that ensures compile-time required and optional fields on cx.
use crate::innerlude::FC;
@@ -50,9 +50,9 @@ pub fn fc_to_builder(_: FC) -> T::Builder {
/// Fragments are incredibly useful when necessary, but *do* add cost in the diffing phase.
/// Try to avoid nesting fragments if you can. Infinitely nested Fragments *will* cause diffing to crash.
#[allow(non_upper_case_globals)]
-pub const Fragment: FC<()> = |ctx| {
+pub const Fragment: FC<()> = |cx| {
use crate::prelude::*;
- ctx.render(LazyNodes::new(move |c| {
- crate::nodebuilder::vfragment(c, None, ctx.children())
+ cx.render(LazyNodes::new(move |c| {
+ crate::nodebuilder::vfragment(c, None, cx.children())
}))
};
diff --git a/packages/core/src/debug_renderer.rs b/packages/core/src/debug_renderer.rs
index 28e906727..82eb10538 100644
--- a/packages/core/src/debug_renderer.rs
+++ b/packages/core/src/debug_renderer.rs
@@ -86,7 +86,7 @@ impl DebugVNodeSource {
}
fn render_nodes(&self) -> VNode {
- // let ctx = NodeCtx
+ // let cx = NodeCtx
todo!()
}
}
@@ -97,9 +97,9 @@ mod tests {
#[test]
fn ensure_creation() -> Result<(), ()> {
- // static Example: FC<()> = |ctx| {
+ // static Example: FC<()> = |cx| {
// //
- // ctx.render(html! {
"hello world"
})
+ // cx.render(html! {
"hello world"
})
// };
// let mut dom = VirtualDom::new(Example);
diff --git a/packages/core/src/events.rs b/packages/core/src/events.rs
index f1f0ed4b4..ab7d966e6 100644
--- a/packages/core/src/events.rs
+++ b/packages/core/src/events.rs
@@ -44,6 +44,9 @@ pub enum VirtualEvent {
MouseEvent(Rc),
PointerEvent(Rc),
+ // Whenever a task is ready (complete) Dioxus produces this "FiberEvent"
+ FiberEvent { task_id: u16 },
+
// image event has conflicting method types
// ImageEvent(event_data::ImageEvent),
OtherEvent,
diff --git a/packages/core/src/hooks.rs b/packages/core/src/hooks.rs
index f908c46bd..3b78405dd 100644
--- a/packages/core/src/hooks.rs
+++ b/packages/core/src/hooks.rs
@@ -28,8 +28,8 @@ mod use_state_def {
///
/// Usage:
/// ```ignore
- /// static Example: FC<()> = |ctx| {
- /// let (counter, set_counter) = use_state(&ctx, || 0);
+ /// static Example: FC<()> = |cx| {
+ /// let (counter, set_counter) = use_state(&cx, || 0);
/// let increment = |_| set_couter(counter + 1);
/// let decrement = |_| set_couter(counter + 1);
///
@@ -43,7 +43,7 @@ mod use_state_def {
/// }
/// ```
pub fn use_state<'a, 'c, T: 'static, F: FnOnce() -> T>(
- ctx: &impl Scoped<'a>,
+ cx: &impl Scoped<'a>,
initial_state_fn: F,
) -> (&'a T, &'a Rc) {
struct UseState {
@@ -52,7 +52,7 @@ mod use_state_def {
caller: Rc,
}
- ctx.use_hook(
+ cx.use_hook(
move || UseState {
new_val: Rc::new(RefCell::new(None)),
current_val: initial_state_fn(),
@@ -61,7 +61,7 @@ mod use_state_def {
move |hook| {
log::debug!("Use_state set called");
let inner = hook.new_val.clone();
- let scheduled_update = ctx.schedule_update();
+ let scheduled_update = cx.schedule_update();
// get ownership of the new val and replace the current with the new
// -> as_ref -> borrow_mut -> deref_mut -> take
@@ -155,8 +155,8 @@ mod new_use_state_def {
///
/// Usage:
/// ```ignore
- /// static Example: FC<()> = |ctx| {
- /// let (counter, set_counter) = use_state(&ctx, || 0);
+ /// static Example: FC<()> = |cx| {
+ /// let (counter, set_counter) = use_state(&cx, || 0);
/// let increment = |_| set_couter(counter + 1);
/// let decrement = |_| set_couter(counter + 1);
///
@@ -170,10 +170,10 @@ mod new_use_state_def {
/// }
/// ```
pub fn use_state_new<'a, 'c, T: 'static, F: FnOnce() -> T>(
- ctx: &impl Scoped<'a>,
+ cx: &impl Scoped<'a>,
initial_state_fn: F,
) -> &'a UseState {
- ctx.use_hook(
+ cx.use_hook(
move || UseState {
modifier: Rc::new(RefCell::new(None)),
current_val: initial_state_fn(),
@@ -182,7 +182,7 @@ mod new_use_state_def {
},
move |hook| {
log::debug!("addr of hook: {:#?}", hook as *const _);
- let scheduled_update = ctx.schedule_update();
+ let scheduled_update = cx.schedule_update();
// log::debug!("Checking if new value {:#?}", &hook.current_val);
// get ownership of the new val and replace the current with the new
@@ -247,10 +247,10 @@ mod use_ref_def {
/// Modifications to this value do not cause updates to the component
/// Attach to inner context reference, so context can be consumed
pub fn use_ref<'a, T: 'static>(
- ctx: &impl Scoped<'a>,
+ cx: &impl Scoped<'a>,
initial_state_fn: impl FnOnce() -> T + 'static,
) -> &'a RefCell {
- ctx.use_hook(|| RefCell::new(initial_state_fn()), |state| &*state, |_| {})
+ cx.use_hook(|| RefCell::new(initial_state_fn()), |state| &*state, |_| {})
}
}
@@ -271,11 +271,11 @@ mod use_reducer_def {
/// This is behaves almost exactly the same way as React's "use_state".
///
pub fn use_reducer<'a, 'c, State: 'static, Action: 'static>(
- ctx: &impl Scoped<'a>,
+ cx: &impl Scoped<'a>,
initial_state_fn: impl FnOnce() -> State,
_reducer: impl Fn(&mut State, Action),
) -> (&'a State, &'a Box) {
- ctx.use_hook(
+ cx.use_hook(
move || UseReducer {
new_val: Rc::new(RefCell::new(None)),
current_val: initial_state_fn(),
@@ -283,7 +283,7 @@ mod use_reducer_def {
},
move |hook| {
let _inner = hook.new_val.clone();
- let scheduled_update = ctx.schedule_update();
+ let scheduled_update = cx.schedule_update();
// get ownership of the new val and replace the current with the new
// -> as_ref -> borrow_mut -> deref_mut -> take
@@ -320,9 +320,9 @@ mod use_reducer_def {
}
// #[allow(unused)]
- // static Example: FC<()> = |ctx| {
+ // static Example: FC<()> = |cx| {
// let (count, reduce) = use_reducer(
- // &ctx,
+ // &cx,
// || 0,
// |count, action| match action {
// Actions::Incr => *count += 1,
@@ -330,7 +330,7 @@ mod use_reducer_def {
// },
// );
- // ctx.render(rsx! {
+ // cx.render(rsx! {
// div {
// h1 {"Count: {count}"}
// button {
@@ -347,8 +347,8 @@ mod use_reducer_def {
}
}
-pub fn use_is_initialized
(ctx: Context
) -> bool {
- let val = use_ref(&ctx, || false);
+pub fn use_is_initialized
(cx: Context
) -> bool {
+ let val = use_ref(&cx, || false);
match *val.borrow() {
true => true,
false => {
diff --git a/packages/core/src/nodebuilder.rs b/packages/core/src/nodebuilder.rs
index 6b526f37b..dccf929fa 100644
--- a/packages/core/src/nodebuilder.rs
+++ b/packages/core/src/nodebuilder.rs
@@ -29,13 +29,14 @@ where
Attributes: 'a + AsRef<[Attribute<'a>]>,
Children: 'a + AsRef<[VNode<'a>]>,
{
- ctx: &'b NodeCtx<'a>,
+ cx: &'b NodeCtx<'a>,
key: NodeKey<'a>,
- tag_name: &'a str,
+ tag_name: &'static str,
+ // tag_name: &'a str,
listeners: Listeners,
attributes: Attributes,
children: Children,
- namespace: Option<&'a str>,
+ namespace: Option<&'static str>,
}
impl<'a, 'b>
@@ -70,10 +71,10 @@ impl<'a, 'b>
/// let my_element_builder = ElementBuilder::new(&b, tag_name);
/// # fn flip_coin() -> bool { true }
/// ```
- pub fn new(ctx: &'b NodeCtx<'a>, tag_name: &'static str) -> Self {
- let bump = ctx.bump();
+ pub fn new(cx: &'b NodeCtx<'a>, tag_name: &'static str) -> Self {
+ let bump = cx.bump();
ElementBuilder {
- ctx,
+ cx,
key: NodeKey::NONE,
tag_name,
listeners: bumpalo::collections::Vec::new_in(bump),
@@ -124,7 +125,7 @@ where
L: 'a + AsRef<[Listener<'a>]>,
{
ElementBuilder {
- ctx: self.ctx,
+ cx: self.cx,
key: self.key,
tag_name: self.tag_name,
listeners,
@@ -163,7 +164,7 @@ where
A: 'a + AsRef<[Attribute<'a>]>,
{
ElementBuilder {
- ctx: self.ctx,
+ cx: self.cx,
key: self.key,
tag_name: self.tag_name,
listeners: self.listeners,
@@ -202,7 +203,7 @@ where
C: 'a + AsRef<[VNode<'a>]>,
{
ElementBuilder {
- ctx: self.ctx,
+ cx: self.cx,
key: self.key,
tag_name: self.tag_name,
listeners: self.listeners,
@@ -227,9 +228,9 @@ where
/// .finish();
/// ```
#[inline]
- pub fn namespace(self, namespace: Option<&'a str>) -> Self {
+ pub fn namespace(self, namespace: Option<&'static str>) -> Self {
ElementBuilder {
- ctx: self.ctx,
+ cx: self.cx,
key: self.key,
tag_name: self.tag_name,
listeners: self.listeners,
@@ -281,7 +282,7 @@ where
Some(static_str) => static_str,
None => {
use bumpalo::core_alloc::fmt::Write;
- let mut s = bumpalo::collections::String::new_in(self.ctx.bump());
+ let mut s = bumpalo::collections::String::new_in(self.cx.bump());
s.write_fmt(args).unwrap();
s.into_bump_str()
}
@@ -307,7 +308,7 @@ where
/// ```
#[inline]
pub fn finish(self) -> VNode<'a> {
- let bump = self.ctx.bump();
+ let bump = self.cx.bump();
let children: &'a Children = bump.alloc(self.children);
let children: &'a [VNode<'a>] = children.as_ref();
@@ -357,11 +358,11 @@ where
/// .finish();
/// ```
pub fn on(self, event: &'static str, callback: impl Fn(VirtualEvent) + 'a) -> Self {
- let bump = &self.ctx.bump();
+ let bump = &self.cx.bump();
let listener = Listener {
event,
callback: bump.alloc(callback),
- scope: self.ctx.scope_ref.arena_idx,
+ scope: self.cx.scope_ref.arena_idx,
mounted_node: bump.alloc(Cell::new(RealDomNode::empty())),
};
self.add_listener(listener)
@@ -371,15 +372,15 @@ where
self.listeners.push(listener);
// bump the context id forward
- let id = self.ctx.listener_id.get();
- self.ctx.listener_id.set(id + 1);
+ let id = self.cx.listener_id.get();
+ self.cx.listener_id.set(id + 1);
// Add this listener to the context list
// This casts the listener to a self-referential pointer
// This is okay because the bump arena is stable
self.listeners.last().map(|g| {
let r = unsafe { std::mem::transmute::<&Listener<'a>, &Listener<'static>>(g) };
- self.ctx
+ self.cx
.scope_ref
.listeners
.borrow_mut()
@@ -413,7 +414,7 @@ where
Some(static_str) => static_str,
None => {
use bumpalo::core_alloc::fmt::Write;
- let mut s = bumpalo::collections::String::new_in(self.ctx.bump());
+ let mut s = bumpalo::collections::String::new_in(self.cx.bump());
s.write_fmt(args).unwrap();
s.into_bump_str()
}
@@ -501,7 +502,7 @@ where
pub fn iter_child(mut self, nodes: impl IntoIterator>) -> Self {
let len_before = self.children.len();
for item in nodes {
- let child = item.into_vnode(&self.ctx);
+ let child = item.into_vnode(&self.cx);
self.children.push(child);
}
if cfg!(debug_assertions) {
@@ -531,20 +532,20 @@ impl<'a> IntoIterator for VNode<'a> {
}
}
impl<'a> IntoVNode<'a> for VNode<'a> {
- fn into_vnode(self, ctx: &NodeCtx<'a>) -> VNode<'a> {
+ fn into_vnode(self, cx: &NodeCtx<'a>) -> VNode<'a> {
self
}
}
impl<'a> IntoVNode<'a> for &VNode<'a> {
- fn into_vnode(self, ctx: &NodeCtx<'a>) -> VNode<'a> {
+ fn into_vnode(self, cx: &NodeCtx<'a>) -> VNode<'a> {
// cloning is cheap since vnodes are just references into bump arenas
self.clone()
}
}
pub trait IntoVNode<'a> {
- fn into_vnode(self, ctx: &NodeCtx<'a>) -> VNode<'a>;
+ fn into_vnode(self, cx: &NodeCtx<'a>) -> VNode<'a>;
}
pub trait VNodeBuilder<'a, G>: IntoIterator
@@ -590,8 +591,8 @@ impl<'a, G> IntoVNode<'a> for LazyNodes<'a, G>
where
G: for<'b> FnOnce(&'b NodeCtx<'a>) -> VNode<'a> + 'a,
{
- fn into_vnode(self, ctx: &NodeCtx<'a>) -> VNode<'a> {
- (self.inner)(ctx)
+ fn into_vnode(self, cx: &NodeCtx<'a>) -> VNode<'a> {
+ (self.inner)(cx)
}
}
@@ -608,14 +609,14 @@ where
}
impl<'a> IntoVNode<'a> for () {
- fn into_vnode(self, ctx: &NodeCtx<'a>) -> VNode<'a> {
+ fn into_vnode(self, cx: &NodeCtx<'a>) -> VNode<'a> {
todo!();
VNode::Suspended
}
}
impl<'a> IntoVNode<'a> for Option<()> {
- fn into_vnode(self, ctx: &NodeCtx<'a>) -> VNode<'a> {
+ fn into_vnode(self, cx: &NodeCtx<'a>) -> VNode<'a> {
todo!();
VNode::Suspended
}
@@ -679,7 +680,7 @@ pub fn attr<'a>(name: &'static str, value: &'a str) -> Attribute<'a> {
}
pub fn virtual_child<'a, T: Properties + 'a>(
- ctx: &NodeCtx<'a>,
+ cx: &NodeCtx<'a>,
f: FC,
props: T,
key: Option<&'a str>, // key: NodeKey<'a>,
@@ -689,37 +690,37 @@ pub fn virtual_child<'a, T: Properties + 'a>(
// might override it with the props macro
// todo!()
VNode::Component(
- ctx.bump()
- .alloc(crate::nodes::VComponent::new(ctx, f, props, key, children)),
- // ctx.bump()
+ cx.bump()
+ .alloc(crate::nodes::VComponent::new(cx, f, props, key, children)),
+ // cx.bump()
// .alloc(crate::nodes::VComponent::new(f, props, key)),
)
}
pub fn vfragment<'a>(
- ctx: &NodeCtx<'a>,
+ cx: &NodeCtx<'a>,
key: Option<&'a str>, // key: NodeKey<'a>,
children: &'a [VNode<'a>],
) -> VNode<'a> {
- VNode::Fragment(ctx.bump().alloc(VFragment::new(key, children)))
+ VNode::Fragment(cx.bump().alloc(VFragment::new(key, children)))
}
pub struct ChildrenList<'a, 'b> {
- ctx: &'b NodeCtx<'a>,
+ cx: &'b NodeCtx<'a>,
children: bumpalo::collections::Vec<'a, VNode<'a>>,
}
impl<'a, 'b> ChildrenList<'a, 'b> {
- pub fn new(ctx: &'b NodeCtx<'a>) -> Self {
+ pub fn new(cx: &'b NodeCtx<'a>) -> Self {
Self {
- ctx,
- children: bumpalo::collections::Vec::new_in(ctx.bump()),
+ cx,
+ children: bumpalo::collections::Vec::new_in(cx.bump()),
}
}
pub fn add_child(mut self, nodes: impl IntoIterator>) -> Self {
for item in nodes {
- let child = item.into_vnode(&self.ctx);
+ let child = item.into_vnode(&self.cx);
self.children.push(child);
}
self
diff --git a/packages/core/src/nodes.rs b/packages/core/src/nodes.rs
index ba98d8e07..c9ebda3b8 100644
--- a/packages/core/src/nodes.rs
+++ b/packages/core/src/nodes.rs
@@ -11,10 +11,8 @@ use crate::{
};
use bumpalo::Bump;
use std::{
- any::Any,
cell::{Cell, RefCell},
fmt::{Arguments, Debug, Formatter},
- marker::PhantomData,
rc::Rc,
};
@@ -56,6 +54,43 @@ impl<'a> Clone for VNode<'a> {
}
}
+impl<'old, 'new> VNode<'old> {
+ // performs a somewhat costly clone of this vnode into another bump
+ // this is used when you want to drag nodes from an old frame into a new frame
+ // There is no way to safely drag listeners over (no way to clone a closure)
+ //
+ // This method will only be called if a component was once a real node and then becomes suspended
+ fn deep_clone_to_new_bump(&self, new: &'new Bump) -> VNode<'new> {
+ match self {
+ VNode::Element(el) => {
+ let new_el: VElement<'new> = VElement {
+ key: NodeKey::NONE,
+ // key: el.key.clone(),
+ tag_name: el.tag_name,
+ // wipe listeners on deep clone, there's no way to know what other bump material they might be referencing (nodes, etc)
+ listeners: &[],
+ attributes: {
+ let attr_vec = bumpalo::collections::Vec::new_in(new);
+ attr_vec.into_bump_slice()
+ },
+ children: {
+ let attr_vec = bumpalo::collections::Vec::new_in(new);
+ attr_vec.into_bump_slice()
+ },
+ namespace: el.namespace.clone(),
+ dom_id: el.dom_id.clone(),
+ };
+
+ VNode::Element(new.alloc_with(move || new_el))
+ }
+ VNode::Text(_) => todo!(),
+ VNode::Fragment(_) => todo!(),
+ VNode::Suspended => todo!(),
+ VNode::Component(_) => todo!(),
+ }
+ }
+}
+
impl<'a> VNode<'a> {
/// Low-level constructor for making a new `Node` of type element with given
/// parts.
@@ -67,11 +102,11 @@ impl<'a> VNode<'a> {
pub fn element(
bump: &'a Bump,
key: NodeKey<'a>,
- tag_name: &'a str,
+ tag_name: &'static str,
listeners: &'a [Listener<'a>],
attributes: &'a [Attribute<'a>],
children: &'a [VNode<'a>],
- namespace: Option<&'a str>,
+ namespace: Option<&'static str>,
) -> VNode<'a> {
let element = bump.alloc_with(|| VElement {
key,
@@ -157,14 +192,16 @@ pub struct VText<'src> {
// ========================================================
// VElement (div, h1, etc), attrs, keys, listener handle
// ========================================================
+
+#[derive(Clone)]
pub struct VElement<'a> {
/// Elements have a tag name, zero or more attributes, and zero or more
pub key: NodeKey<'a>,
- pub tag_name: &'a str,
+ pub tag_name: &'static str,
pub listeners: &'a [Listener<'a>],
pub attributes: &'a [Attribute<'a>],
pub children: &'a [VNode<'a>],
- pub namespace: Option<&'a str>,
+ pub namespace: Option<&'static str>,
pub dom_id: Cell,
}
@@ -298,13 +335,13 @@ impl<'a> VComponent<'a> {
///
/// If the CanMemo is `false`, then the macro will call the backup method which always defaults to "false"
pub fn new(
- ctx: &NodeCtx<'a>,
+ cx: &NodeCtx<'a>,
component: FC
,
props: P,
key: Option<&'a str>,
children: &'a [VNode<'a>],
) -> Self {
- let bump = ctx.bump();
+ let bump = cx.bump();
let user_fc = component as *const ();
let props = bump.alloc(props);
@@ -370,13 +407,13 @@ fn create_closure<'a, P: 'a>(
let g: Captured = Rc::new(move |scp: &Scope| -> VNode {
// cast back into the right lifetime
let safe_props: &'_ P = unsafe { &*(raw_props as *const P) };
- // let ctx: Context = todo!();
- let ctx: Context
= Context {
+ // let cx: Context = todo!();
+ let cx: Context
= Context {
props: safe_props,
scope: scp,
};
- let g = component(ctx);
+ let g = component(cx);
let g2 = unsafe { std::mem::transmute(g) };
g2
});
diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs
index 9b43779f5..b18735cbe 100644
--- a/packages/core/src/virtual_dom.rs
+++ b/packages/core/src/virtual_dom.rs
@@ -21,6 +21,7 @@
use crate::{arena::ScopeArena, innerlude::*};
use bumpalo::Bump;
+use futures::FutureExt;
use generational_arena::Arena;
use std::{
any::{Any, TypeId},
@@ -55,7 +56,7 @@ pub struct VirtualDom {
#[doc(hidden)]
_root_caller: Rc,
// _root_caller: Rc>,
- /// Type of the original ctx. This is stored as TypeId so VirtualDom does not need to be generic.
+ /// Type of the original cx. This is stored as TypeId so VirtualDom does not need to be generic.
///
/// Whenver props need to be updated, an Error will be thrown if the new props do not
/// match the props used to create the VirtualDom.
@@ -90,12 +91,12 @@ impl VirtualDom {
/// ```ignore
/// // Directly from a closure
///
- /// let dom = VirtualDom::new(|ctx| ctx.render(rsx!{ div {"hello world"} }));
+ /// let dom = VirtualDom::new(|cx| cx.render(rsx!{ div {"hello world"} }));
///
/// // or pass in...
///
- /// let root = |ctx| {
- /// ctx.render(rsx!{
+ /// let root = |cx| {
+ /// cx.render(rsx!{
/// div {"hello world"}
/// })
/// }
@@ -103,8 +104,8 @@ impl VirtualDom {
///
/// // or directly from a fn
///
- /// fn Example(ctx: Context<()>) -> VNode {
- /// ctx.render(rsx!{ div{"hello world"} })
+ /// fn Example(cx: Context<()>) -> VNode {
+ /// cx.render(rsx!{ div{"hello world"} })
/// }
///
/// let dom = VirtualDom::new(Example);
@@ -113,7 +114,7 @@ impl VirtualDom {
Self::new_with_props(root, ())
}
- /// Start a new VirtualDom instance with a dependent ctx.
+ /// Start a new VirtualDom instance with a dependent cx.
/// Later, the props can be updated by calling "update" with a new set of props, causing a set of re-renders.
///
/// This is useful when a component tree can be driven by external state (IE SSR) but it would be too expensive
@@ -122,12 +123,12 @@ impl VirtualDom {
/// ```ignore
/// // Directly from a closure
///
- /// let dom = VirtualDom::new(|ctx| ctx.render(rsx!{ div {"hello world"} }));
+ /// let dom = VirtualDom::new(|cx| cx.render(rsx!{ div {"hello world"} }));
///
/// // or pass in...
///
- /// let root = |ctx| {
- /// ctx.render(rsx!{
+ /// let root = |cx| {
+ /// cx.render(rsx!{
/// div {"hello world"}
/// })
/// }
@@ -135,8 +136,8 @@ impl VirtualDom {
///
/// // or directly from a fn
///
- /// fn Example(ctx: Context, props: &SomeProps) -> VNode {
- /// ctx.render(rsx!{ div{"hello world"} })
+ /// fn Example(cx: Context, props: &SomeProps) -> VNode {
+ /// cx.render(rsx!{ div{"hello world"} })
/// }
///
/// let dom = VirtualDom::new(Example);
@@ -395,11 +396,13 @@ pub struct Scope {
// Stores references into the listeners attached to the vnodes
// NEEDS TO BE PRIVATE
pub(crate) listeners: RefCell, *const dyn Fn(VirtualEvent))>>,
+
+ pub(crate) suspended_tasks: Vec>>>,
// pub(crate) listeners: RefCell>,
// pub(crate) listeners: RefCell>,
// pub(crate) listeners: RefCell>,
// NoHashMap
- // pub(crate) listeners: RefCell>,
+ // pub(crate) listeners: RefCell>
}
// We need to pin the hook so it doesn't move as we initialize the list of hooks
@@ -465,6 +468,7 @@ impl Scope {
listeners: Default::default(),
hookidx: Default::default(),
descendents: Default::default(),
+ suspended_tasks: Default::default(),
}
}
@@ -588,9 +592,9 @@ impl Scope {
///
/// }
///
-/// fn example(ctx: Context, props: &Props -> VNode {
+/// fn example(cx: Context, props: &Props -> VNode {
/// html! {
-///
"Hello, {ctx.ctx.name}"
+///
"Hello, {cx.cx.name}"
/// }
/// }
/// ```
@@ -645,6 +649,14 @@ pub trait Scoped<'src>: Sized {
self.get_scope().event_channel.clone()
}
+ fn schedule_effect(&self) -> Rc {
+ todo!()
+ }
+
+ fn schedule_layout_effect(&self) {
+ todo!()
+ }
+
/// Take a lazy VNode structure and actually build it with the context of the VDom's efficient VNode allocator.
///
/// This function consumes the context and absorb the lifetime, so these VNodes *must* be returned.
@@ -652,12 +664,12 @@ pub trait Scoped<'src>: Sized {
/// ## Example
///
/// ```ignore
- /// fn Component(ctx: Context<()>) -> VNode {
+ /// fn Component(cx: Context<()>) -> VNode {
/// // Lazy assemble the VNode tree
/// let lazy_tree = html! {
"Hello World"
};
///
/// // Actually build the tree and allocate it
- /// ctx.render(lazy_tree)
+ /// cx.render(lazy_tree)
/// }
///```
fn render<'a, F: for<'b> FnOnce(&'b NodeCtx<'src>) -> VNode<'src> + 'src + 'a>(
@@ -750,7 +762,7 @@ Any function prefixed with "use" should not be called conditionally.
///
fn use_create_context(&self, init: impl Fn() -> T) {
let scope = self.get_scope();
- let mut ctxs = scope.shared_contexts.borrow_mut();
+ let mut cxs = scope.shared_contexts.borrow_mut();
let ty = TypeId::of::();
let is_initialized = self.use_hook(
@@ -763,14 +775,14 @@ Any function prefixed with "use" should not be called conditionally.
|_| {},
);
- match (is_initialized, ctxs.contains_key(&ty)) {
+ match (is_initialized, cxs.contains_key(&ty)) {
// Do nothing, already initialized and already exists
(true, true) => {}
// Needs to be initialized
(false, false) => {
log::debug!("Initializing context...");
- ctxs.insert(ty, Rc::new(init()));
+ cxs.insert(ty, Rc::new(init()));
}
_ => debug_assert!(false, "Cannot initialize two contexts of the same type"),
@@ -810,9 +822,9 @@ Any function prefixed with "use" should not be called conditionally.
log::debug!("Searching {:#?} for valid shared_context", inner.arena_idx);
let shared_contexts = inner.shared_contexts.borrow();
- if let Some(shared_ctx) = shared_contexts.get(&ty) {
- log::debug!("found matching ctx");
- let rc = shared_ctx
+ if let Some(shared_cx) = shared_contexts.get(&ty) {
+ log::debug!("found matching cx");
+ let rc = shared_cx
.clone()
.downcast::()
.expect("Should not fail, already validated the type from the hashmap");
@@ -841,10 +853,32 @@ Any function prefixed with "use" should not be called conditionally.
)
}
- fn suspend(
+ fn suspend(
&self,
- f: impl Future