diff --git a/.vscode/settings.json b/.vscode/settings.json
index 2f418701b..80f51cff8 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,3 +1,3 @@
{
- "rust-analyzer.inlayHints.enable": true
+ "rust-analyzer.inlayHints.enable": false
}
\ No newline at end of file
diff --git a/packages/core/examples/sketch.rs b/packages/core/examples/sketch.rs
index 61ff2c8ba..5f09da37b 100644
--- a/packages/core/examples/sketch.rs
+++ b/packages/core/examples/sketch.rs
@@ -1,6 +1,7 @@
use bumpalo::Bump;
+use dioxus_core as dioxus;
use dioxus_core::{
- prelude::{Context, VElement, VNode, FC},
+ prelude::{html, Context, VElement, VNode, FC},
virtual_dom::{Properties, Scope},
};
use std::{
@@ -135,26 +136,50 @@ fn test_use_state(ctx: Context<()>) -> VNode {
// whenever a listener wakes up, we take the reference directly from the bump arena and, with a small bit
// of unsafe code, execute the associated closure / listener function
// Those vnodes are then tossed out and new ones are installed, meaning and old references (potentially bad)
- // are removed and UB is prevented from affecting the program
+ // are removed and UB is prevented from /affecting/ the program
{
VNode::Element(VElement::new("button"))
}
}
-fn test_use_state_2(ctx: Context<()>) -> VNode {
+#[allow(unused, non_upper_case_globals)]
+static UseStateBorrowedFc: FC<()> = |ctx| {
let (val, set_val) = use_state(&ctx, || 0);
let incr = || set_val(val + 1);
let decr = || set_val(val - 1);
- todo!()
- // html! {
- //
- //
- //
{ "Current value: {val}" }
- //
- // }
+ ctx.view(html! {
+
+
+
"Current value: {val}"
+
+ })
+};
+
+/// A useful component
+/// With some great documentation
+/// it practically speaks for itself.
+/// It's also only a server component :o
+fn use_state_borrowed(ctx: Context<()>) -> VNode {
+ let (val, set_val) = use_state(&ctx, || 0);
+
+ let incr = || set_val(val + 1);
+ let decr = || set_val(val - 1);
+
+ ctx.view(html! {
+
+
+
"Current value: {val}"
+
+ })
}
+
+//
+//
diff --git a/packages/core/examples/step.rs b/packages/core/examples/step.rs
new file mode 100644
index 000000000..36b94153b
--- /dev/null
+++ b/packages/core/examples/step.rs
@@ -0,0 +1,36 @@
+//! An example that shows how to:
+//! create a scope,
+//! render a component,
+//! change some data
+//! render it again
+//! consume the diffs and write that to a renderer
+
+use dioxus_core::{
+ prelude::*,
+ virtual_dom::{Properties, Scope},
+};
+
+fn main() {
+ let mut scope = Scope::new(Example);
+ let ctx = scope.create_context::();
+ let p1 = Props { name: "bob".into() };
+
+ let p2 = Props { name: "bob".into() };
+}
+
+struct Props {
+ name: String,
+}
+impl Properties for Props {
+ fn new() -> Self {
+ todo!()
+ }
+}
+
+static Example: FC = |ctx| {
+ ctx.view(html! {
+
+
+
+ })
+};
diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs
index 45f9d2eee..8fff4ff45 100644
--- a/packages/core/src/virtual_dom.rs
+++ b/packages/core/src/virtual_dom.rs
@@ -49,10 +49,11 @@ A Context
*/
use crate::nodes::VNode;
use crate::prelude::*;
+use any::Any;
use bumpalo::Bump;
use generational_arena::{Arena, Index};
use std::{
- any::TypeId,
+ any::{self, TypeId},
cell::{RefCell, UnsafeCell},
future::Future,
marker::PhantomData,
@@ -279,6 +280,7 @@ pub struct Scope {
arena: typed_arena::Arena,
hooks: RefCell>,
props_type: TypeId,
+ caller: *const (),
}
impl Scope {
@@ -289,10 +291,13 @@ impl Scope {
let arena = typed_arena::Arena::new();
let hooks = RefCell::new(Vec::new());
+ let caller = f as *const ();
+
Self {
arena,
hooks,
props_type,
+ caller,
}
}
@@ -308,7 +313,26 @@ impl Scope {
/// Create a new context and run the component with references from the Virtual Dom
/// This function downcasts the function pointer based on the stored props_type
- fn run() {}
+ fn run(&self, f: FC) {}
+
+ fn call(&mut self, val: T) {
+ if self.props_type == TypeId::of::() {
+ /*
+ SAFETY ALERT
+
+ This particular usage of transmute is outlined in its docs https://doc.rust-lang.org/std/mem/fn.transmute.html
+ We hide the generic bound on the function item by casting it to raw pointer. When the function is actually called,
+ we transmute the function back using the props as reference.
+
+ This is safe because we check that the generic type matches before casting.
+ */
+ let caller = unsafe { std::mem::transmute::<*const (), FC>(self.caller) };
+ let ctx = self.create_context::();
+ let nodes = caller(ctx);
+ } else {
+ panic!("Do not try to use `call` on Scopes with the wrong props type")
+ }
+ }
}
/// Components in Dioxus use the "Context" object to interact with their lifecycle.