feat: transition to cx, props
This commit is contained in:
1 parent
f1cff845ce
commit
bfdcb20437
14 files changed
+88
-50
No files matched your search
@@ -29,7 +29,7 @@ use crate::innerlude::{Context, DomTree, LazyNodes, FC};
|
|||||||
/// You want to use this free-function when your fragment needs a key and simply returning multiple nodes from rsx! won't cut it.
|
/// You want to use this free-function when your fragment needs a key and simply returning multiple nodes from rsx! won't cut it.
|
||||||
///
|
///
|
||||||
#[allow(non_upper_case_globals, non_snake_case)]
|
#[allow(non_upper_case_globals, non_snake_case)]
|
||||||
pub fn Fragment<'a>(cx: Context<'a, ()>) -> DomTree<'a> {
|
pub fn Fragment<'a>(cx: Context<'a>, props: &'a ()) -> DomTree<'a> {
|
||||||
cx.render(LazyNodes::new(|f| f.fragment_from_iter(cx.children())))
|
cx.render(LazyNodes::new(|f| f.fragment_from_iter(cx.children())))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,16 +27,15 @@ use std::{any::TypeId, ops::Deref, rc::Rc};
|
|||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub struct Context<'src, T> {
|
pub struct Context<'src> {
|
||||||
pub props: &'src T,
|
|
||||||
pub scope: &'src Scope,
|
pub scope: &'src Scope,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src, T> Copy for Context<'src, T> {}
|
impl<'src> Copy for Context<'src> {}
|
||||||
impl<'src, T> Clone for Context<'src, T> {
|
impl<'src> Clone for Context<'src> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
props: self.props,
|
// props: self.props,
|
||||||
scope: self.scope,
|
scope: self.scope,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,14 +43,14 @@ impl<'src, T> Clone for Context<'src, T> {
|
|||||||
|
|
||||||
// We currently deref to props, but it might make more sense to deref to Scope?
|
// We currently deref to props, but it might make more sense to deref to Scope?
|
||||||
// This allows for code that takes cx.xyz instead of cx.props.xyz
|
// This allows for code that takes cx.xyz instead of cx.props.xyz
|
||||||
impl<'a, T> Deref for Context<'a, T> {
|
impl<'a> Deref for Context<'a> {
|
||||||
type Target = &'a T;
|
type Target = &'a Scope;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.props
|
&self.scope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src, P> Context<'src, P> {
|
impl<'src> Context<'src> {
|
||||||
/// Access the children elements passed into the component
|
/// Access the children elements passed into the component
|
||||||
///
|
///
|
||||||
/// This enables patterns where a component is passed children from its parent.
|
/// This enables patterns where a component is passed children from its parent.
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ use std::{
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
pub fn use_task<'src, Out, Fut, Init, P>(
|
pub fn use_task<'src, Out, Fut, Init>(
|
||||||
cx: Context<'src, P>,
|
cx: Context<'src>,
|
||||||
task_initializer: Init,
|
task_initializer: Init,
|
||||||
) -> (&'src TaskHandle, &'src Option<Out>)
|
) -> (&'src TaskHandle, &'src Option<Out>)
|
||||||
where
|
where
|
||||||
@@ -83,8 +83,8 @@ where
|
|||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
pub fn use_suspense<'src, Out, Fut, Cb, P>(
|
pub fn use_suspense<'src, Out, Fut, Cb>(
|
||||||
cx: Context<'src, P>,
|
cx: Context<'src>,
|
||||||
task_initializer: impl FnOnce() -> Fut,
|
task_initializer: impl FnOnce() -> Fut,
|
||||||
user_callback: Cb,
|
user_callback: Cb,
|
||||||
) -> DomTree<'src>
|
) -> DomTree<'src>
|
||||||
@@ -123,10 +123,7 @@ where
|
|||||||
Some(value) => {
|
Some(value) => {
|
||||||
let out = value.downcast_ref::<Out>().unwrap();
|
let out = value.downcast_ref::<Out>().unwrap();
|
||||||
let sus = SuspendedContext {
|
let sus = SuspendedContext {
|
||||||
inner: Context {
|
inner: Context { scope: cx.scope },
|
||||||
props: &(),
|
|
||||||
scope: cx.scope,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
user_callback(sus, out)
|
user_callback(sus, out)
|
||||||
}
|
}
|
||||||
@@ -171,7 +168,7 @@ pub(crate) struct SuspenseHook {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct SuspendedContext<'a> {
|
pub struct SuspendedContext<'a> {
|
||||||
pub(crate) inner: Context<'a, ()>,
|
pub(crate) inner: Context<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> SuspendedContext<'src> {
|
impl<'src> SuspendedContext<'src> {
|
||||||
@@ -196,7 +193,7 @@ impl<'a, T> Deref for NodeRef<'a, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn use_node_ref<T, P>(cx: Context<P>) -> NodeRef<T> {
|
pub fn use_node_ref<T, P>(cx: Context) -> NodeRef<T> {
|
||||||
cx.use_hook(
|
cx.use_hook(
|
||||||
|f| {},
|
|f| {},
|
||||||
|f| {
|
|f| {
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ pub(crate) mod innerlude {
|
|||||||
pub use crate::virtual_dom::*;
|
pub use crate::virtual_dom::*;
|
||||||
|
|
||||||
pub type DomTree<'a> = Option<VNode<'a>>;
|
pub type DomTree<'a> = Option<VNode<'a>>;
|
||||||
pub type FC<P> = fn(Context<P>) -> DomTree;
|
pub type FC<P> = for<'a> fn(Context<'a>, &'a P) -> DomTree<'a>;
|
||||||
|
|
||||||
pub use dioxus_core_macro::{format_args_f, html, rsx};
|
pub use dioxus_core_macro::{format_args_f, html, rsx};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -511,7 +511,7 @@ impl<'a> NodeFactory<'a> {
|
|||||||
let caller: &'a mut dyn for<'b> Fn(&'b Scope) -> DomTree<'b> =
|
let caller: &'a mut dyn for<'b> Fn(&'b Scope) -> DomTree<'b> =
|
||||||
bump.alloc(move |scope: &Scope| -> DomTree {
|
bump.alloc(move |scope: &Scope| -> DomTree {
|
||||||
let props: &'_ P = unsafe { &*(raw_props as *const P) };
|
let props: &'_ P = unsafe { &*(raw_props as *const P) };
|
||||||
let res = component(Context { props, scope });
|
let res = component(Context { scope }, props);
|
||||||
unsafe { std::mem::transmute(res) }
|
unsafe { std::mem::transmute(res) }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -275,10 +275,7 @@ impl Scope {
|
|||||||
let sus: &'a VSuspended<'a> = unsafe { std::mem::transmute(sus) };
|
let sus: &'a VSuspended<'a> = unsafe { std::mem::transmute(sus) };
|
||||||
|
|
||||||
let cx: SuspendedContext<'a> = SuspendedContext {
|
let cx: SuspendedContext<'a> = SuspendedContext {
|
||||||
inner: Context {
|
inner: Context { scope: self },
|
||||||
props: &(),
|
|
||||||
scope: self,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut cb = sus.callback.borrow_mut().take().unwrap();
|
let mut cb = sus.callback.borrow_mut().take().unwrap();
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ impl VirtualDom {
|
|||||||
// Safety: this callback is only valid for the lifetime of the root props
|
// Safety: this callback is only valid for the lifetime of the root props
|
||||||
let root_caller: Box<dyn Fn(&Scope) -> DomTree> = Box::new(move |scope: &Scope| unsafe {
|
let root_caller: Box<dyn Fn(&Scope) -> DomTree> = Box::new(move |scope: &Scope| unsafe {
|
||||||
let props: &'_ P = &*(props_ptr as *const P);
|
let props: &'_ P = &*(props_ptr as *const P);
|
||||||
std::mem::transmute(root(Context { props, scope }))
|
std::mem::transmute(root(Context { scope }, props))
|
||||||
});
|
});
|
||||||
|
|
||||||
let scheduler = Scheduler::new();
|
let scheduler = Scheduler::new();
|
||||||
@@ -203,7 +203,7 @@ impl VirtualDom {
|
|||||||
let root_caller: Box<dyn Fn(&Scope) -> DomTree> =
|
let root_caller: Box<dyn Fn(&Scope) -> DomTree> =
|
||||||
Box::new(move |scope: &Scope| unsafe {
|
Box::new(move |scope: &Scope| unsafe {
|
||||||
let props: &'_ P = &*(props_ptr as *const P);
|
let props: &'_ P = &*(props_ptr as *const P);
|
||||||
std::mem::transmute(root(Context { props, scope }))
|
std::mem::transmute(root(Context { scope }, props))
|
||||||
});
|
});
|
||||||
|
|
||||||
root_scope.update_scope_dependencies(&root_caller, ScopeChildren(&[]));
|
root_scope.update_scope_dependencies(&root_caller, ScopeChildren(&[]));
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
use dioxus::{nodes::VSuspended, prelude::*, DomEdit, TestDom};
|
||||||
|
use dioxus_core as dioxus;
|
||||||
|
use dioxus_html as dioxus_elements;
|
||||||
|
|
||||||
|
static Parent: FC<()> = |cx, props| {
|
||||||
|
//
|
||||||
|
let value = cx.use_hook(|_| String::new(), |f| &*f, |_| {});
|
||||||
|
|
||||||
|
cx.render(rsx! {
|
||||||
|
div {
|
||||||
|
Child { name: value }
|
||||||
|
Child { name: value }
|
||||||
|
Child { name: value }
|
||||||
|
Child { name: value }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Props)]
|
||||||
|
struct ChildProps<'a> {
|
||||||
|
name: &'a String,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Child<'a>(cx: Context<'a>, props: &'a ChildProps) -> DomTree<'a> {
|
||||||
|
cx.render(rsx! {
|
||||||
|
div {
|
||||||
|
h1 { "it's nested" }
|
||||||
|
Child2 { name: props.name }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Props)]
|
||||||
|
struct Grandchild<'a> {
|
||||||
|
name: &'a String,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Child2<'a>(cx: Context<'a>, props: &Grandchild) -> DomTree<'a> {
|
||||||
|
cx.render(rsx! {
|
||||||
|
div { "Hello {props.name}!" }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_borrowed_state() {}
|
||||||
@@ -18,7 +18,7 @@ fn new_dom<P: Properties + 'static>(app: FC<P>, props: P) -> VirtualDom {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_original_diff() {
|
fn test_original_diff() {
|
||||||
static APP: FC<()> = |cx| {
|
static APP: FC<()> = |cx, props| {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div {
|
||||||
div {
|
div {
|
||||||
@@ -48,7 +48,7 @@ fn test_original_diff() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create() {
|
fn create() {
|
||||||
static APP: FC<()> = |cx| {
|
static APP: FC<()> = |cx, props| {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div {
|
||||||
div {
|
div {
|
||||||
@@ -99,7 +99,7 @@ fn create() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_list() {
|
fn create_list() {
|
||||||
static APP: FC<()> = |cx| {
|
static APP: FC<()> = |cx, props| {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
{(0..3).map(|f| rsx!{ div {
|
{(0..3).map(|f| rsx!{ div {
|
||||||
"hello"
|
"hello"
|
||||||
@@ -139,7 +139,7 @@ fn create_list() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_simple() {
|
fn create_simple() {
|
||||||
static APP: FC<()> = |cx| {
|
static APP: FC<()> = |cx, props| {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {}
|
div {}
|
||||||
div {}
|
div {}
|
||||||
@@ -165,7 +165,7 @@ fn create_simple() {
|
|||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn create_components() {
|
fn create_components() {
|
||||||
static App: FC<()> = |cx| {
|
static App: FC<()> = |cx, props| {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
Child { "abc1" }
|
Child { "abc1" }
|
||||||
Child { "abc2" }
|
Child { "abc2" }
|
||||||
@@ -173,7 +173,7 @@ fn create_components() {
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
static Child: FC<()> = |cx| {
|
static Child: FC<()> = |cx, props| {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
h1 {}
|
h1 {}
|
||||||
div { {cx.children()} }
|
div { {cx.children()} }
|
||||||
@@ -217,7 +217,7 @@ fn create_components() {
|
|||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn anchors() {
|
fn anchors() {
|
||||||
static App: FC<()> = |cx| {
|
static App: FC<()> = |cx, props| {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
{true.then(|| rsx!{ div { "hello" } })}
|
{true.then(|| rsx!{ div { "hello" } })}
|
||||||
{false.then(|| rsx!{ div { "goodbye" } })}
|
{false.then(|| rsx!{ div { "goodbye" } })}
|
||||||
@@ -243,7 +243,7 @@ fn anchors() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn suspended() {
|
fn suspended() {
|
||||||
static App: FC<()> = |cx| {
|
static App: FC<()> = |cx, props| {
|
||||||
let val = use_suspense(
|
let val = use_suspense(
|
||||||
cx,
|
cx,
|
||||||
|| async {
|
|| async {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const IS_LOGGING_ENABLED: bool = true;
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn please_work() {
|
fn please_work() {
|
||||||
static App: FC<()> = |cx| {
|
static App: FC<()> = |cx, props| {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div {
|
||||||
hidden: "true"
|
hidden: "true"
|
||||||
@@ -29,7 +29,7 @@ fn please_work() {
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
static Child: FC<()> = |cx| {
|
static Child: FC<()> = |cx, props| {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div { "child" }
|
div { "child" }
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use dioxus_html as dioxus_elements;
|
|||||||
|
|
||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
async fn event_queue_works() {
|
async fn event_queue_works() {
|
||||||
static App: FC<()> = |cx| {
|
static App: FC<()> = |cx, props| {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div { "hello world" }
|
div { "hello world" }
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ fn manual_diffing() {
|
|||||||
value: Shared<&'static str>,
|
value: Shared<&'static str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
static App: FC<AppProps> = |cx| {
|
static App: FC<AppProps> = |cx, props| {
|
||||||
let val = cx.value.borrow();
|
let val = props.value.borrow();
|
||||||
cx.render(rsx! { div { "{val}" } })
|
cx.render(rsx! { div { "{val}" } })
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ fn new_dom() -> TestDom {
|
|||||||
fn shared_state_test() {
|
fn shared_state_test() {
|
||||||
struct MySharedState(&'static str);
|
struct MySharedState(&'static str);
|
||||||
|
|
||||||
static App: FC<()> = |cx| {
|
static App: FC<()> = |cx, props| {
|
||||||
cx.use_provide_state(|| MySharedState("world!"));
|
cx.use_provide_state(|| MySharedState("world!"));
|
||||||
rsx!(cx, Child {})
|
rsx!(cx, Child {})
|
||||||
};
|
};
|
||||||
|
|
||||||
static Child: FC<()> = |cx| {
|
static Child: FC<()> = |cx, props| {
|
||||||
let shared = cx.use_consume_state::<MySharedState>()?;
|
let shared = cx.use_consume_state::<MySharedState>()?;
|
||||||
rsx!(cx, "Hello, {shared.0}")
|
rsx!(cx, "Hello, {shared.0}")
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use dioxus_html as dioxus_elements;
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn app_runs() {
|
fn app_runs() {
|
||||||
static App: FC<()> = |cx| {
|
static App: FC<()> = |cx, props| {
|
||||||
//
|
//
|
||||||
cx.render(rsx!( div{"hello"} ))
|
cx.render(rsx!( div{"hello"} ))
|
||||||
};
|
};
|
||||||
@@ -25,7 +25,7 @@ fn app_runs() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn fragments_work() {
|
fn fragments_work() {
|
||||||
static App: FC<()> = |cx| {
|
static App: FC<()> = |cx, props| {
|
||||||
cx.render(rsx!(
|
cx.render(rsx!(
|
||||||
div{"hello"}
|
div{"hello"}
|
||||||
div{"goodbye"}
|
div{"goodbye"}
|
||||||
@@ -39,7 +39,7 @@ fn fragments_work() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn lists_work() {
|
fn lists_work() {
|
||||||
static App: FC<()> = |cx| {
|
static App: FC<()> = |cx, props| {
|
||||||
cx.render(rsx!(
|
cx.render(rsx!(
|
||||||
h1 {"hello"}
|
h1 {"hello"}
|
||||||
{(0..6).map(|f| rsx!(span{ "{f}" }))}
|
{(0..6).map(|f| rsx!(span{ "{f}" }))}
|
||||||
@@ -52,7 +52,7 @@ fn lists_work() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn conditional_rendering() {
|
fn conditional_rendering() {
|
||||||
static App: FC<()> = |cx| {
|
static App: FC<()> = |cx, props| {
|
||||||
cx.render(rsx!(
|
cx.render(rsx!(
|
||||||
h1 {"hello"}
|
h1 {"hello"}
|
||||||
{true.then(|| rsx!(span{ "a" }))}
|
{true.then(|| rsx!(span{ "a" }))}
|
||||||
@@ -69,13 +69,13 @@ fn conditional_rendering() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn child_components() {
|
fn child_components() {
|
||||||
static App: FC<()> = |cx| {
|
static App: FC<()> = |cx, props| {
|
||||||
cx.render(rsx!(
|
cx.render(rsx!(
|
||||||
{true.then(|| rsx!(Child { }))}
|
{true.then(|| rsx!(Child { }))}
|
||||||
{false.then(|| rsx!(Child { }))}
|
{false.then(|| rsx!(Child { }))}
|
||||||
))
|
))
|
||||||
};
|
};
|
||||||
static Child: FC<()> = |cx| {
|
static Child: FC<()> = |cx, props| {
|
||||||
cx.render(rsx!(
|
cx.render(rsx!(
|
||||||
h1 {"hello"}
|
h1 {"hello"}
|
||||||
h1 {"goodbye"}
|
h1 {"goodbye"}
|
||||||
@@ -88,7 +88,7 @@ fn child_components() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn suspended_works() {
|
fn suspended_works() {
|
||||||
static App: FC<()> = |cx| {
|
static App: FC<()> = |cx, props| {
|
||||||
let title = use_suspense(cx, || async { "bob" }, |cx, f| cx.render(rsx! { "{f}"}));
|
let title = use_suspense(cx, || async { "bob" }, |cx, f| cx.render(rsx! { "{f}"}));
|
||||||
cx.render(rsx!("hello" { title }))
|
cx.render(rsx!("hello" { title }))
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in new issue
Block a user