feat: transition to cx, props

This commit is contained in:
Jonathan Kelley committed 2021-09-21 13:13:15 -04:00
1 parent f1cff845ce
commit bfdcb20437
14 files changed
+88 -50

No files matched your search

+1 -1
View File
@@ -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())))
} }
+8 -9
View File
@@ -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.
+7 -10
View File
@@ -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| {
+1 -1
View File
@@ -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};
} }
+1 -1
View File
@@ -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) }
}); });
+1 -4
View File
@@ -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();
+2 -2
View File
@@ -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(&[]));
+45
View File
@@ -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() {}
+8 -8
View File
@@ -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 {
+2 -2
View File
@@ -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" }
}) })
+1 -1
View File
@@ -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" }
}) })
+2 -2
View File
@@ -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}" } })
}; };
+2 -2
View File
@@ -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}")
}; };
+7 -7
View File
@@ -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 }))
}; };