wip: go back to noisy lifetime solution
This commit is contained in:
1 parent
0545d27182
commit
8daf7a6ed8
31 files changed
+214
-170
No files matched your search
@@ -20,7 +20,7 @@ fn main() {
|
|||||||
dioxus::desktop::launch(App, |c| c);
|
dioxus::desktop::launch(App, |c| c);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn App(cx: Context, props: &()) -> Element {
|
fn App(cx: Scope, props: &()) -> Element {
|
||||||
let text: &mut Vec<String> = cx.use_hook(|_| vec![String::from("abc=def")], |f| f);
|
let text: &mut Vec<String> = cx.use_hook(|_| vec![String::from("abc=def")], |f| f);
|
||||||
|
|
||||||
let first = text.get_mut(0).unwrap();
|
let first = text.get_mut(0).unwrap();
|
||||||
@@ -39,7 +39,7 @@ struct C1Props<'a> {
|
|||||||
text: &'a mut String,
|
text: &'a mut String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Child1(cx: Context, props: &C1Props) -> Element {
|
fn Child1(cx: Scope, props: &C1Props) -> Element {
|
||||||
let (left, right) = props.text.split_once("=").unwrap();
|
let (left, right) = props.text.split_once("=").unwrap();
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
@@ -55,7 +55,7 @@ struct C2Props<'a> {
|
|||||||
text: &'a str,
|
text: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Child2(cx: Context, props: &C2Props) -> Element {
|
fn Child2(cx: Scope, props: &C2Props) -> Element {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
Child3 {
|
Child3 {
|
||||||
text: props.text
|
text: props.text
|
||||||
@@ -68,7 +68,7 @@ struct C3Props<'a> {
|
|||||||
text: &'a str,
|
text: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Child3(cx: Context, props: &C3Props) -> Element {
|
fn Child3(cx: Scope, props: &C3Props) -> Element {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div { "{props.text}"}
|
div { "{props.text}"}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ struct CalculatorKeyProps<'a> {
|
|||||||
children: Element,
|
children: Element,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn CalculatorKey<'a>(cx: Context, props: &CalculatorKeyProps) -> Element {
|
fn CalculatorKey<'a>(cx: Scope, props: &CalculatorKeyProps) -> Element {
|
||||||
rsx!(cx, button {
|
rsx!(cx, button {
|
||||||
class: "calculator-key {props.name}"
|
class: "calculator-key {props.name}"
|
||||||
onclick: {props.onclick}
|
onclick: {props.onclick}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ struct HorseyProps<'a> {
|
|||||||
children: ScopeChildren<'a>,
|
children: ScopeChildren<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Horsey<'a>((cx, props): Scope<'a, HorseyProps<'a>>) -> Element {
|
fn Horsey<'a>((cx, props): ScopeState<'a, HorseyProps<'a>>) -> Element {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div {
|
||||||
button { "pause" }
|
button { "pause" }
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ struct ActionButtonProps<'a> {
|
|||||||
onclick: &'a dyn Fn(),
|
onclick: &'a dyn Fn(),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ActionButton(cx: Context, props: &ActionButtonProps) -> Element {
|
fn ActionButton(cx: Scope, props: &ActionButtonProps) -> Element {
|
||||||
rsx!(cx, div { class: "col-sm-6 smallpad"
|
rsx!(cx, div { class: "col-sm-6 smallpad"
|
||||||
button { class:"btn btn-primary btn-block", r#type: "button", id: "{props.id}", onclick: move |_| (props.onclick)(),
|
button { class:"btn btn-primary btn-block", r#type: "button", id: "{props.id}", onclick: move |_| (props.onclick)(),
|
||||||
"{props.name}"
|
"{props.name}"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ fn main() {
|
|||||||
dioxus::desktop::launch(App, |c| c);
|
dioxus::desktop::launch(App, |c| c);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn App((cx, props): Scope<()>) -> Element {
|
fn App((cx, props): ScopeState<()>) -> Element {
|
||||||
cx.render(rsx! (
|
cx.render(rsx! (
|
||||||
div { "Hello, world!" }
|
div { "Hello, world!" }
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ struct CalculatorKeyProps<'a> {
|
|||||||
children: ScopeChildren<'a>,
|
children: ScopeChildren<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn CalculatorKey<'a>((cx, props): Scope<'a, CalculatorKeyProps<'a>>) -> Element<'a> {
|
fn CalculatorKey<'a>((cx, props): ScopeState<'a, CalculatorKeyProps<'a>>) -> Element<'a> {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
button {
|
button {
|
||||||
class: "calculator-key {props.name}"
|
class: "calculator-key {props.name}"
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ pub static Example: Component<()> = |cx, props| {
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
fn helper(cx: Context, text: &str) -> Element {
|
fn helper(cx: Scope, text: &str) -> Element {
|
||||||
rsx!(cx, p { "{text}" })
|
rsx!(cx, p { "{text}" })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +188,7 @@ mod baller {
|
|||||||
pub struct BallerProps {}
|
pub struct BallerProps {}
|
||||||
|
|
||||||
/// This component totally balls
|
/// This component totally balls
|
||||||
pub fn Baller(_: Scope<BallerProps>) -> Element {
|
pub fn Baller(_: ScopeState<BallerProps>) -> Element {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,7 +202,7 @@ pub struct TallerProps<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// This component is taller than most :)
|
/// This component is taller than most :)
|
||||||
pub fn Taller<'a>(_: Scope<'a, TallerProps<'a>>) -> Element {
|
pub fn Taller<'a>(_: ScopeState<'a, TallerProps<'a>>) -> Element {
|
||||||
let b = true;
|
let b = true;
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
+1
-1
@@ -21,6 +21,6 @@ static App: Component<()> = |cx, props| {
|
|||||||
struct MyProps<'a> {
|
struct MyProps<'a> {
|
||||||
text: &'a str,
|
text: &'a str,
|
||||||
}
|
}
|
||||||
fn App2(cx: Context, props: &MyProps) -> Element {
|
fn App2(cx: Scope, props: &MyProps) -> Element {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
+1
-1
@@ -85,7 +85,7 @@ pub struct TodoEntryProps {
|
|||||||
todo: Rc<TodoItem>,
|
todo: Rc<TodoItem>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn TodoEntry(cx: Context, props: &TodoEntryProps) -> Element {
|
pub fn TodoEntry(cx: Scope, props: &TodoEntryProps) -> Element {
|
||||||
let mut is_editing = use_state(cx, || false);
|
let mut is_editing = use_state(cx, || false);
|
||||||
let mut contents = use_state(cx, || String::from(""));
|
let mut contents = use_state(cx, || String::from(""));
|
||||||
let todo = &props.todo;
|
let todo = &props.todo;
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ struct RowProps {
|
|||||||
row_id: usize,
|
row_id: usize,
|
||||||
label: Label,
|
label: Label,
|
||||||
}
|
}
|
||||||
fn Row((cx, props): Scope<RowProps>) -> Element {
|
fn Row((cx, props): ScopeState<RowProps>) -> Element {
|
||||||
let [adj, col, noun] = props.label.0;
|
let [adj, col, noun] = props.label.0;
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
tr {
|
tr {
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ struct RowProps {
|
|||||||
row_id: usize,
|
row_id: usize,
|
||||||
label: Label,
|
label: Label,
|
||||||
}
|
}
|
||||||
fn Row(cx: Context, props: &RowProps) -> Element {
|
fn Row(cx: Scope, props: &RowProps) -> Element {
|
||||||
let [adj, col, noun] = props.label.0;
|
let [adj, col, noun] = props.label.0;
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
tr {
|
tr {
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
use dioxus::prelude::*;
|
||||||
|
use dioxus_core as dioxus;
|
||||||
|
use dioxus_core_macro::*;
|
||||||
|
use dioxus_html as dioxus_elements;
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
|
|
||||||
|
fn App(cx: Scope<()>) -> Element {
|
||||||
|
cx.render(rsx!(div {
|
||||||
|
App2 {
|
||||||
|
p: "asd"
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Props)]
|
||||||
|
struct Borrowed<'a> {
|
||||||
|
p: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn App2<'a>(cx: Scope<'a, Borrowed<'a>>) -> Element {
|
||||||
|
let g = eat2(&cx);
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eat2(s: &ScopeState) {}
|
||||||
|
|
||||||
|
fn eat(f: &str) {}
|
||||||
|
|
||||||
|
fn bleat() {
|
||||||
|
let blah = String::from("asd");
|
||||||
|
eat(&blah);
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct Lower {}
|
||||||
|
|
||||||
|
// #[derive(Clone, Copy)]
|
||||||
|
// struct Upper {}
|
||||||
|
// impl std::ops::Deref for Upper {
|
||||||
|
// type Target = Lower;
|
||||||
|
|
||||||
|
// fn deref(&self) -> &Self::Target {
|
||||||
|
// todo!()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn mark(f: &Lower) {}
|
||||||
|
// fn bark() {
|
||||||
|
// let up = Upper {};
|
||||||
|
// mark(&up);
|
||||||
|
// }
|
||||||
@@ -9,7 +9,7 @@ fn main() {
|
|||||||
let _ = VirtualDom::new(App);
|
let _ = VirtualDom::new(App);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn App(cx: Context, _props: &()) -> Element {
|
fn App(cx: Scope<()>) -> Element {
|
||||||
//
|
//
|
||||||
cx.render(rsx!(
|
cx.render(rsx!(
|
||||||
div {
|
div {
|
||||||
@@ -18,11 +18,7 @@ fn App(cx: Context, _props: &()) -> Element {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ChildProps<'a> {
|
fn Child(cx: Scope<()>) -> Element {
|
||||||
click_handler: EventHandler<'a>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn Child(cx: Context, _props: &()) -> Element {
|
|
||||||
//
|
//
|
||||||
cx.render(rsx!(
|
cx.render(rsx!(
|
||||||
div {
|
div {
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ struct RowProps {
|
|||||||
row_id: usize,
|
row_id: usize,
|
||||||
label: Label,
|
label: Label,
|
||||||
}
|
}
|
||||||
fn Row(cx: Context, props: &RowProps) -> Element {
|
fn Row(cx: Scope, props: &RowProps) -> Element {
|
||||||
let [adj, col, noun] = props.label.0;
|
let [adj, col, noun] = props.label.0;
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
tr {
|
tr {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ fn main() {
|
|||||||
let _ = VirtualDom::new(Parent);
|
let _ = VirtualDom::new(Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Parent(cx: Context, _props: &()) -> Element {
|
fn Parent(cx: Scope, _props: &()) -> Element {
|
||||||
let value = cx.use_hook(|_| String::new(), |f| f);
|
let value = cx.use_hook(|_| String::new(), |f| f);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
@@ -25,7 +25,7 @@ struct ChildProps<'a> {
|
|||||||
name: &'a str,
|
name: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Child(cx: Context, props: &ChildProps) -> Element {
|
fn Child(cx: Scope, props: &ChildProps) -> Element {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div {
|
||||||
h1 { "it's nested" }
|
h1 { "it's nested" }
|
||||||
@@ -39,7 +39,7 @@ struct Grandchild<'a> {
|
|||||||
name: &'a str,
|
name: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Child2(cx: Context, props: &Grandchild) -> Element {
|
fn Child2(cx: Scope, props: &Grandchild) -> Element {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div { "Hello {props.name}!" }
|
div { "Hello {props.name}!" }
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -5,17 +5,18 @@
|
|||||||
//! if the type supports PartialEq. The Properties trait is used by the rsx! and html! macros to generate the type-safe builder
|
//! if the type supports 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 cx.
|
//! that ensures compile-time required and optional fields on cx.
|
||||||
|
|
||||||
use crate::innerlude::{Context, Element, LazyNodes, VPortal};
|
use crate::innerlude::{Element, LazyNodes, Scope, VPortal};
|
||||||
|
|
||||||
pub struct FragmentProps(Element);
|
pub struct FragmentProps<'a>(Element<'a>);
|
||||||
pub struct FragmentBuilder<const BUILT: bool>(Element);
|
pub struct FragmentBuilder<'a, const BUILT: bool>(Element<'a>);
|
||||||
impl FragmentBuilder<false> {
|
impl<'a> FragmentBuilder<'a, false> {
|
||||||
pub fn children(self, children: Option<VPortal>) -> FragmentBuilder<true> {
|
pub fn children(self, children: Element<'a>) -> FragmentBuilder<'a, true> {
|
||||||
FragmentBuilder(children)
|
todo!()
|
||||||
|
// FragmentBuilder(children)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<const A: bool> FragmentBuilder<A> {
|
impl<'a, const A: bool> FragmentBuilder<'a, A> {
|
||||||
pub fn build(self) -> FragmentProps {
|
pub fn build(self) -> FragmentProps<'a> {
|
||||||
FragmentProps(self.0)
|
FragmentProps(self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,8 +61,8 @@ impl<const A: bool> FragmentBuilder<A> {
|
|||||||
/// })
|
/// })
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
impl Properties for FragmentProps {
|
impl<'a> Properties for FragmentProps<'a> {
|
||||||
type Builder = FragmentBuilder<false>;
|
type Builder = FragmentBuilder<'a, false>;
|
||||||
const IS_STATIC: bool = false;
|
const IS_STATIC: bool = false;
|
||||||
fn builder() -> Self::Builder {
|
fn builder() -> Self::Builder {
|
||||||
FragmentBuilder(None)
|
FragmentBuilder(None)
|
||||||
@@ -97,8 +98,9 @@ impl Properties for FragmentProps {
|
|||||||
///
|
///
|
||||||
/// 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(cx: Context<FragmentProps>) -> Element {
|
pub fn Fragment<'a>(cx: Scope<'a, FragmentProps<'a>>) -> Element {
|
||||||
cx.render(Some(LazyNodes::new(|f| f.fragment_from_iter(&cx.props.0))))
|
todo!()
|
||||||
|
// cx.render(Some(LazyNodes::new(|f| f.fragment_from_iter(&cx.props.0))))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Every "Props" used for a component must implement the `Properties` trait. This trait gives some hints to Dioxus
|
/// Every "Props" used for a component must implement the `Properties` trait. This trait gives some hints to Dioxus
|
||||||
@@ -165,6 +167,6 @@ impl EmptyBuilder {
|
|||||||
|
|
||||||
/// This utility function launches the builder method so rsx! and html! macros can use the typed-builder pattern
|
/// This utility function launches the builder method so rsx! and html! macros can use the typed-builder pattern
|
||||||
/// to initialize a component's props.
|
/// to initialize a component's props.
|
||||||
pub fn fc_to_builder<'a, T: Properties + 'a>(_: fn(Context<'a, T>) -> Element) -> T::Builder {
|
pub fn fc_to_builder<'a, T: Properties + 'a>(_: fn(Scope<'a, T>) -> Element) -> T::Builder {
|
||||||
T::builder()
|
T::builder()
|
||||||
}
|
}
|
||||||
@@ -1370,7 +1370,7 @@ impl<'bump> DiffState<'bump> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a listener closure to a scope during diff.
|
/// Adds a listener closure to a scope during diff.
|
||||||
fn attach_listener_to_scope(&mut self, listener: &'bump Listener<'bump>, scope: &Scope) {
|
fn attach_listener_to_scope(&mut self, listener: &'bump Listener<'bump>, scope: &ScopeState) {
|
||||||
let long_listener = unsafe { std::mem::transmute(listener) };
|
let long_listener = unsafe { std::mem::transmute(listener) };
|
||||||
scope.items.borrow_mut().listeners.push(long_listener)
|
scope.items.borrow_mut().listeners.push(long_listener)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,21 +20,21 @@ pub(crate) mod innerlude {
|
|||||||
pub(crate) use crate::scopearena::*;
|
pub(crate) use crate::scopearena::*;
|
||||||
pub use crate::virtual_dom::*;
|
pub use crate::virtual_dom::*;
|
||||||
|
|
||||||
pub type Element = Option<VPortal>;
|
pub type Element<'a> = Option<VNode<'a>>;
|
||||||
pub type Component<P> = for<'a> fn(Context<'a, P>) -> Element;
|
pub type Component<P> = for<'a> fn(Scope<'a, P>) -> Element<'a>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use crate::innerlude::{
|
pub use crate::innerlude::{
|
||||||
AnyContext, Attribute, Component, Context, DioxusElement, DomEdit, Element, ElementId,
|
Attribute, Component, DioxusElement, DomEdit, Element, ElementId, EventHandler, EventPriority,
|
||||||
EventHandler, EventPriority, IntoVNode, LazyNodes, Listener, Mutations, NodeFactory,
|
IntoVNode, LazyNodes, Listener, Mutations, NodeFactory, Properties, SchedulerMsg, Scope,
|
||||||
Properties, SchedulerMsg, Scope, ScopeId, UserEvent, VElement, VFragment, VNode, VirtualDom,
|
ScopeId, ScopeState, UserEvent, VElement, VFragment, VNode, VirtualDom,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use crate::component::{fc_to_builder, Fragment, Properties};
|
pub use crate::component::{fc_to_builder, Fragment, Properties};
|
||||||
pub use crate::innerlude::Context;
|
pub use crate::innerlude::Scope;
|
||||||
pub use crate::innerlude::{
|
pub use crate::innerlude::{
|
||||||
AnyContext, Component, DioxusElement, Element, EventHandler, LazyNodes, NodeFactory, Scope,
|
Component, DioxusElement, Element, EventHandler, LazyNodes, NodeFactory, ScopeState,
|
||||||
};
|
};
|
||||||
pub use crate::nodes::VNode;
|
pub use crate::nodes::VNode;
|
||||||
pub use crate::VirtualDom;
|
pub use crate::VirtualDom;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
//! cheap and *very* fast to construct - building a full tree should be quick.
|
//! cheap and *very* fast to construct - building a full tree should be quick.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
innerlude::{Context, Element, Properties, Scope, ScopeId},
|
innerlude::{Element, Properties, Scope, ScopeId, ScopeState},
|
||||||
lazynodes::LazyNodes,
|
lazynodes::LazyNodes,
|
||||||
};
|
};
|
||||||
use bumpalo::{boxed::Box as BumpBox, Bump};
|
use bumpalo::{boxed::Box as BumpBox, Bump};
|
||||||
@@ -412,7 +412,7 @@ pub struct VComponent<'src> {
|
|||||||
pub(crate) bump_props: *const (),
|
pub(crate) bump_props: *const (),
|
||||||
|
|
||||||
// during the "teardown" process we'll take the caller out so it can be dropped properly
|
// during the "teardown" process we'll take the caller out so it can be dropped properly
|
||||||
pub(crate) caller: &'src dyn Fn(&'src Scope) -> Element,
|
pub(crate) caller: &'src dyn Fn(&'src ScopeState) -> Element,
|
||||||
|
|
||||||
pub(crate) comparator: Option<&'src dyn Fn(&VComponent) -> bool>,
|
pub(crate) comparator: Option<&'src dyn Fn(&VComponent) -> bool>,
|
||||||
|
|
||||||
@@ -554,7 +554,7 @@ impl<'a> NodeFactory<'a> {
|
|||||||
|
|
||||||
pub fn component<P>(
|
pub fn component<P>(
|
||||||
&self,
|
&self,
|
||||||
component: fn(Context<'a, P>) -> Element,
|
component: fn(Scope<'a, P>) -> Element,
|
||||||
props: P,
|
props: P,
|
||||||
key: Option<Arguments>,
|
key: Option<Arguments>,
|
||||||
) -> VNode<'a>
|
) -> VNode<'a>
|
||||||
@@ -612,10 +612,10 @@ impl<'a> NodeFactory<'a> {
|
|||||||
|
|
||||||
let key = key.map(|f| self.raw_text(f).0);
|
let key = key.map(|f| self.raw_text(f).0);
|
||||||
|
|
||||||
let caller: &'a mut dyn Fn(&'a Scope) -> Element =
|
let caller: &'a mut dyn Fn(&'a ScopeState) -> Element =
|
||||||
bump.alloc(move |scope: &Scope| -> Element {
|
bump.alloc(move |scope: &ScopeState| -> Element {
|
||||||
let props: &'_ P = unsafe { &*(bump_props as *const P) };
|
let props: &'_ P = unsafe { &*(bump_props as *const P) };
|
||||||
component(Context { scope, props })
|
component(Scope { scope, props })
|
||||||
});
|
});
|
||||||
|
|
||||||
let can_memoize = P::IS_STATIC;
|
let can_memoize = P::IS_STATIC;
|
||||||
@@ -707,7 +707,7 @@ impl<'a> NodeFactory<'a> {
|
|||||||
pub fn create_children(
|
pub fn create_children(
|
||||||
self,
|
self,
|
||||||
node_iter: impl IntoIterator<Item = impl IntoVNode<'a>>,
|
node_iter: impl IntoIterator<Item = impl IntoVNode<'a>>,
|
||||||
) -> Element {
|
) -> Element<'a> {
|
||||||
let bump = self.bump;
|
let bump = self.bump;
|
||||||
let mut nodes = bumpalo::collections::Vec::new_in(bump);
|
let mut nodes = bumpalo::collections::Vec::new_in(bump);
|
||||||
|
|
||||||
@@ -726,16 +726,10 @@ impl<'a> NodeFactory<'a> {
|
|||||||
// TODO
|
// TODO
|
||||||
// We need a dedicated path in the rsx! macro that will trigger the "you need keys" warning
|
// We need a dedicated path in the rsx! macro that will trigger the "you need keys" warning
|
||||||
|
|
||||||
let frag = VNode::Fragment(VFragment {
|
Some(VNode::Fragment(VFragment {
|
||||||
children,
|
children,
|
||||||
key: None,
|
key: None,
|
||||||
});
|
}))
|
||||||
let ptr = self.bump.alloc(frag) as *const _;
|
|
||||||
Some(VPortal {
|
|
||||||
link_idx: Default::default(),
|
|
||||||
scope_id: Default::default(),
|
|
||||||
node: unsafe { std::mem::transmute(ptr) },
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+64
-49
@@ -31,11 +31,39 @@ use bumpalo::{boxed::Box as BumpBox, Bump};
|
|||||||
/// cx.render(rsx!{ div {"Hello, {props.name}"} })
|
/// cx.render(rsx!{ div {"Hello, {props.name}"} })
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub struct Context<'a, P: 'static> {
|
pub struct Scope<'a, P> {
|
||||||
pub scope: &'a Scope,
|
pub scope: &'a ScopeState,
|
||||||
pub props: &'a P,
|
pub props: &'a P,
|
||||||
}
|
}
|
||||||
impl<P> Clone for Context<'_, P> {
|
|
||||||
|
impl<'a, P> Scope<'a, P> {
|
||||||
|
/// 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.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// fn Component(cx: Scope, props: &Props) -> Element {
|
||||||
|
/// // Lazy assemble the VNode tree
|
||||||
|
/// let lazy_nodes = rsx!("hello world");
|
||||||
|
///
|
||||||
|
/// // Actually build the tree and allocate it
|
||||||
|
/// cx.render(lazy_tree)
|
||||||
|
/// }
|
||||||
|
///```
|
||||||
|
pub fn render(self, rsx: Option<LazyNodes<'a, '_>>) -> Option<VNode<'a>> {
|
||||||
|
let fac = NodeFactory {
|
||||||
|
bump: &self.scope.wip_frame().bump,
|
||||||
|
};
|
||||||
|
match rsx {
|
||||||
|
Some(s) => Some(s.call(fac)),
|
||||||
|
None => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P> Clone for Scope<'_, P> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
scope: self.scope,
|
scope: self.scope,
|
||||||
@@ -43,21 +71,13 @@ impl<P> Clone for Context<'_, P> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<P> Copy for Context<'_, P> {}
|
impl<P> Copy for Scope<'_, P> {}
|
||||||
impl<P> std::ops::Deref for Context<'_, P> {
|
impl<P> std::ops::Deref for Scope<'_, P> {
|
||||||
type Target = Scope;
|
type Target = ScopeState;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.scope
|
&self.scope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub trait AnyContext<'a> {
|
|
||||||
fn get_scope(&self) -> &'a Scope;
|
|
||||||
}
|
|
||||||
impl<'a, P> AnyContext<'a> for Context<'a, P> {
|
|
||||||
fn get_scope(&self) -> &'a Scope {
|
|
||||||
&self.scope
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A component's unique identifier.
|
/// A component's unique identifier.
|
||||||
///
|
///
|
||||||
@@ -76,8 +96,8 @@ pub struct ScopeId(pub usize);
|
|||||||
///
|
///
|
||||||
/// We expose the `Scope` type so downstream users can traverse the Dioxus VirtualDOM for whatever
|
/// We expose the `Scope` type so downstream users can traverse the Dioxus VirtualDOM for whatever
|
||||||
/// use case they might have.
|
/// use case they might have.
|
||||||
pub struct Scope {
|
pub struct ScopeState {
|
||||||
pub(crate) parent_scope: Option<*mut Scope>,
|
pub(crate) parent_scope: Option<*mut ScopeState>,
|
||||||
|
|
||||||
pub(crate) container: ElementId,
|
pub(crate) container: ElementId,
|
||||||
|
|
||||||
@@ -93,7 +113,7 @@ pub struct Scope {
|
|||||||
|
|
||||||
pub(crate) frames: [BumpFrame; 2],
|
pub(crate) frames: [BumpFrame; 2],
|
||||||
|
|
||||||
pub(crate) caller: *const dyn Fn(&Scope) -> Element,
|
pub(crate) caller: *const dyn Fn(&ScopeState) -> Element,
|
||||||
|
|
||||||
pub(crate) items: RefCell<SelfReferentialItems<'static>>,
|
pub(crate) items: RefCell<SelfReferentialItems<'static>>,
|
||||||
|
|
||||||
@@ -113,7 +133,7 @@ pub struct SelfReferentialItems<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Public methods exposed to libraries and components
|
// Public methods exposed to libraries and components
|
||||||
impl Scope {
|
impl ScopeState {
|
||||||
/// Get the subtree ID that this scope belongs to.
|
/// Get the subtree ID that this scope belongs to.
|
||||||
///
|
///
|
||||||
/// Each component has its own subtree ID - the root subtree has an ID of 0. This ID is used by the renderer to route
|
/// Each component has its own subtree ID - the root subtree has an ID of 0. This ID is used by the renderer to route
|
||||||
@@ -342,36 +362,31 @@ impl Scope {
|
|||||||
items.tasks.len() - 1
|
items.tasks.len() - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Take a lazy VNode structure and actually build it with the context of the VDom's efficient VNode allocator.
|
// /// 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.
|
// /// This function consumes the context and absorb the lifetime, so these VNodes *must* be returned.
|
||||||
///
|
// ///
|
||||||
/// ## Example
|
// /// ## Example
|
||||||
///
|
// ///
|
||||||
/// ```ignore
|
// /// ```ignore
|
||||||
/// fn Component(cx: Scope, props: &Props) -> Element {
|
// /// fn Component(cx: Scope, props: &Props) -> Element {
|
||||||
/// // Lazy assemble the VNode tree
|
// /// // Lazy assemble the VNode tree
|
||||||
/// let lazy_nodes = rsx!("hello world");
|
// /// let lazy_nodes = rsx!("hello world");
|
||||||
///
|
// ///
|
||||||
/// // Actually build the tree and allocate it
|
// /// // Actually build the tree and allocate it
|
||||||
/// cx.render(lazy_tree)
|
// /// cx.render(lazy_tree)
|
||||||
/// }
|
// /// }
|
||||||
///```
|
// ///```
|
||||||
pub fn render<'src>(&'src self, rsx: Option<LazyNodes<'src, '_>>) -> Option<VPortal> {
|
// pub fn render<'src>(&self, rsx: Option<LazyNodes<'src, '_>>) -> Option<VNode<'src>> {
|
||||||
let bump = &self.wip_frame().bump;
|
// let fac = NodeFactory {
|
||||||
|
// bump: &self.wip_frame().bump,
|
||||||
let owned_node: VNode<'src> = rsx.map(|f| f.call(NodeFactory { bump }))?;
|
// };
|
||||||
let alloced_vnode: &'src mut VNode<'src> = bump.alloc(owned_node);
|
// match rsx {
|
||||||
let node_ptr: *mut VNode<'src> = alloced_vnode as *mut _;
|
// Some(s) => Some(s.call(fac)),
|
||||||
|
// None => todo!(),
|
||||||
let node: *mut VNode<'static> = unsafe { std::mem::transmute(node_ptr) };
|
// }
|
||||||
|
// // rsx.map(|f| f.call(fac))
|
||||||
Some(VPortal {
|
// }
|
||||||
scope_id: Cell::new(Some(self.our_arena_idx)),
|
|
||||||
link_idx: Cell::new(0),
|
|
||||||
node,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Store a value between renders
|
/// Store a value between renders
|
||||||
///
|
///
|
||||||
@@ -505,5 +520,5 @@ impl BumpFrame {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn sizeof() {
|
fn sizeof() {
|
||||||
dbg!(std::mem::size_of::<Scope>());
|
dbg!(std::mem::size_of::<ScopeState>());
|
||||||
}
|
}
|
||||||
@@ -24,9 +24,9 @@ pub(crate) struct ScopeArena {
|
|||||||
bump: Bump,
|
bump: Bump,
|
||||||
pub pending_futures: RefCell<FxHashSet<ScopeId>>,
|
pub pending_futures: RefCell<FxHashSet<ScopeId>>,
|
||||||
scope_counter: Cell<usize>,
|
scope_counter: Cell<usize>,
|
||||||
pub scopes: RefCell<FxHashMap<ScopeId, *mut Scope>>,
|
pub scopes: RefCell<FxHashMap<ScopeId, *mut ScopeState>>,
|
||||||
pub heuristics: RefCell<FxHashMap<FcSlot, Heuristic>>,
|
pub heuristics: RefCell<FxHashMap<FcSlot, Heuristic>>,
|
||||||
free_scopes: RefCell<Vec<*mut Scope>>,
|
free_scopes: RefCell<Vec<*mut ScopeState>>,
|
||||||
nodes: RefCell<Slab<*const VNode<'static>>>,
|
nodes: RefCell<Slab<*const VNode<'static>>>,
|
||||||
pub(crate) sender: UnboundedSender<SchedulerMsg>,
|
pub(crate) sender: UnboundedSender<SchedulerMsg>,
|
||||||
}
|
}
|
||||||
@@ -68,23 +68,23 @@ impl ScopeArena {
|
|||||||
/// Safety:
|
/// Safety:
|
||||||
/// - Obtaining a mutable refernece to any Scope is unsafe
|
/// - Obtaining a mutable refernece to any Scope is unsafe
|
||||||
/// - Scopes use interior mutability when sharing data into components
|
/// - Scopes use interior mutability when sharing data into components
|
||||||
pub(crate) fn get_scope(&self, id: &ScopeId) -> Option<&Scope> {
|
pub(crate) fn get_scope(&self, id: &ScopeId) -> Option<&ScopeState> {
|
||||||
unsafe { self.scopes.borrow().get(id).map(|f| &**f) }
|
unsafe { self.scopes.borrow().get(id).map(|f| &**f) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn get_scope_raw(&self, id: &ScopeId) -> Option<*mut Scope> {
|
pub(crate) unsafe fn get_scope_raw(&self, id: &ScopeId) -> Option<*mut ScopeState> {
|
||||||
self.scopes.borrow().get(id).copied()
|
self.scopes.borrow().get(id).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn get_scope_mut(&self, id: &ScopeId) -> Option<&mut Scope> {
|
pub(crate) unsafe fn get_scope_mut(&self, id: &ScopeId) -> Option<&mut ScopeState> {
|
||||||
self.scopes.borrow().get(id).map(|s| &mut **s)
|
self.scopes.borrow().get(id).map(|s| &mut **s)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new_with_key(
|
pub(crate) fn new_with_key(
|
||||||
&self,
|
&self,
|
||||||
fc_ptr: *const (),
|
fc_ptr: *const (),
|
||||||
caller: *const dyn Fn(&Scope) -> Element,
|
caller: *const dyn Fn(&ScopeState) -> Element,
|
||||||
parent_scope: Option<*mut Scope>,
|
parent_scope: Option<*mut ScopeState>,
|
||||||
container: ElementId,
|
container: ElementId,
|
||||||
height: u32,
|
height: u32,
|
||||||
subtree: u32,
|
subtree: u32,
|
||||||
@@ -160,7 +160,7 @@ impl ScopeArena {
|
|||||||
unsafe { std::mem::transmute(vnode as *mut VNode) }
|
unsafe { std::mem::transmute(vnode as *mut VNode) }
|
||||||
});
|
});
|
||||||
|
|
||||||
let scope = self.bump.alloc(Scope {
|
let scope = self.bump.alloc(ScopeState {
|
||||||
sender: self.sender.clone(),
|
sender: self.sender.clone(),
|
||||||
container,
|
container,
|
||||||
our_arena_idx: new_scope_id,
|
our_arena_idx: new_scope_id,
|
||||||
@@ -330,18 +330,9 @@ impl ScopeArena {
|
|||||||
scope.wip_frame().nodes.borrow_mut().clear();
|
scope.wip_frame().nodes.borrow_mut().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
let render: &dyn Fn(&Scope) -> Element = unsafe { &*scope.caller };
|
let render: &dyn Fn(&ScopeState) -> Element = unsafe { &*scope.caller };
|
||||||
|
|
||||||
if let Some(link) = render(scope) {
|
if let Some(link) = render(scope) {
|
||||||
// right now, it's a panic to render a nodelink from another scope
|
|
||||||
// todo: enable this. it should (reasonably) work even if it doesnt make much sense
|
|
||||||
assert_eq!(link.scope_id.get(), Some(*id));
|
|
||||||
|
|
||||||
// nodelinks are not assigned when called and must be done so through the create/diff phase
|
|
||||||
// however, we need to link this one up since it will never be used in diffing
|
|
||||||
scope.wip_frame().assign_nodelink(&link);
|
|
||||||
debug_assert_eq!(scope.wip_frame().nodes.borrow().len(), 1);
|
|
||||||
|
|
||||||
if !scope.items.borrow().tasks.is_empty() {
|
if !scope.items.borrow().tasks.is_empty() {
|
||||||
self.pending_futures.borrow_mut().insert(*id);
|
self.pending_futures.borrow_mut().insert(*id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -196,13 +196,18 @@ impl VirtualDom {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
let scopes = ScopeArena::new(sender.clone());
|
let scopes = ScopeArena::new(sender.clone());
|
||||||
|
|
||||||
let mut caller = Box::new(move |scp: &Scope| -> Element {
|
let root_props = Box::new(root_props);
|
||||||
root(Context {
|
let props_ref: *const P = root_props.as_ref();
|
||||||
scope: scp,
|
let mut caller: Box<dyn Fn(&ScopeState) -> Element> =
|
||||||
props: &root_props,
|
Box::new(move |scp: &ScopeState| -> Element {
|
||||||
})
|
let p = unsafe { &*props_ref };
|
||||||
});
|
todo!()
|
||||||
let caller_ref: *mut dyn Fn(&Scope) -> Element = caller.as_mut() as *mut _;
|
// root(Context {
|
||||||
|
// scope: scp,
|
||||||
|
// props: p,
|
||||||
|
// })
|
||||||
|
});
|
||||||
|
let caller_ref: *mut dyn Fn(&ScopeState) -> Element = caller.as_mut();
|
||||||
let base_scope = scopes.new_with_key(root as _, caller_ref, None, ElementId(0), 0, 0);
|
let base_scope = scopes.new_with_key(root as _, caller_ref, None, ElementId(0), 0, 0);
|
||||||
|
|
||||||
let pending_messages = VecDeque::new();
|
let pending_messages = VecDeque::new();
|
||||||
@@ -213,7 +218,7 @@ impl VirtualDom {
|
|||||||
scopes: Box::new(scopes),
|
scopes: Box::new(scopes),
|
||||||
base_scope,
|
base_scope,
|
||||||
receiver,
|
receiver,
|
||||||
_root_props: caller,
|
_root_props: root_props,
|
||||||
pending_messages,
|
pending_messages,
|
||||||
dirty_scopes,
|
dirty_scopes,
|
||||||
sender,
|
sender,
|
||||||
@@ -226,7 +231,7 @@ impl VirtualDom {
|
|||||||
/// directly.
|
/// directly.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
pub fn base_scope(&self) -> &Scope {
|
pub fn base_scope(&self) -> &ScopeState {
|
||||||
self.get_scope(&self.base_scope).unwrap()
|
self.get_scope(&self.base_scope).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,7 +241,7 @@ impl VirtualDom {
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
pub fn get_scope<'a>(&'a self, id: &ScopeId) -> Option<&'a Scope> {
|
pub fn get_scope<'a>(&'a self, id: &ScopeId) -> Option<&'a ScopeState> {
|
||||||
self.scopes.get_scope(id)
|
self.scopes.get_scope(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ fn test_borrowed_state() {
|
|||||||
let _ = VirtualDom::new(Parent);
|
let _ = VirtualDom::new(Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Parent(cx: Context, _props: &()) -> Element {
|
fn Parent(cx: Scope, _props: &()) -> Element {
|
||||||
let value = cx.use_hook(|_| String::new(), |f| &*f);
|
let value = cx.use_hook(|_| String::new(), |f| &*f);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
@@ -28,7 +28,7 @@ struct ChildProps<'a> {
|
|||||||
name: &'a str,
|
name: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Child(cx: Context, props: &ChildProps) -> Element {
|
fn Child(cx: Scope, props: &ChildProps) -> Element {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div {
|
||||||
h1 { "it's nested" }
|
h1 { "it's nested" }
|
||||||
@@ -42,7 +42,7 @@ struct Grandchild<'a> {
|
|||||||
name: &'a str,
|
name: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Child2(cx: Context, props: &Grandchild) -> Element {
|
fn Child2(cx: Scope, props: &Grandchild) -> Element {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div { "Hello {props.name}!" }
|
div { "Hello {props.name}!" }
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ fn create_components() {
|
|||||||
children: Element,
|
children: Element,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Child(cx: Context, props: &ChildProps) -> Element {
|
fn Child(cx: Scope, props: &ChildProps) -> Element {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
h1 {}
|
h1 {}
|
||||||
div { {&props.children} }
|
div { {&props.children} }
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use dioxus_core::{AnyContext, Scope, ScopeId};
|
use dioxus_core::{ScopeId, ScopeState};
|
||||||
use std::{
|
use std::{
|
||||||
cell::{Cell, Ref, RefCell, RefMut},
|
cell::{Cell, Ref, RefCell, RefMut},
|
||||||
collections::HashSet,
|
collections::HashSet,
|
||||||
@@ -59,8 +59,7 @@ impl<T> ProvidedStateInner<T> {
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
pub fn use_shared_state<'a, T: 'static>(cx: &dyn AnyContext<'a>) -> Option<UseSharedState<'a, T>> {
|
pub fn use_shared_state<'a, T: 'static>(cx: &'a ScopeState) -> Option<UseSharedState<'a, T>> {
|
||||||
let cx = cx.get_scope();
|
|
||||||
cx.use_hook(
|
cx.use_hook(
|
||||||
|_| {
|
|_| {
|
||||||
let scope_id = cx.scope_id();
|
let scope_id = cx.scope_id();
|
||||||
@@ -111,7 +110,7 @@ impl<T> Drop for SharedStateInner<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct UseSharedState<'a, T: 'static> {
|
pub struct UseSharedState<'a, T: 'static> {
|
||||||
pub(crate) cx: &'a Scope,
|
pub(crate) cx: &'a ScopeState,
|
||||||
pub(crate) value: &'a Rc<RefCell<T>>,
|
pub(crate) value: &'a Rc<RefCell<T>>,
|
||||||
pub(crate) root: &'a Rc<RefCell<ProvidedStateInner<T>>>,
|
pub(crate) root: &'a Rc<RefCell<ProvidedStateInner<T>>>,
|
||||||
pub(crate) needs_notification: &'a Cell<bool>,
|
pub(crate) needs_notification: &'a Cell<bool>,
|
||||||
@@ -176,8 +175,7 @@ where
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
pub fn use_provide_state<'a, T: 'static>(cx: &dyn AnyContext<'a>, f: impl FnOnce() -> T) {
|
pub fn use_provide_state<'a, T: 'static>(cx: &'a ScopeState, f: impl FnOnce() -> T) {
|
||||||
let cx = cx.get_scope();
|
|
||||||
cx.use_hook(
|
cx.use_hook(
|
||||||
|_| {
|
|_| {
|
||||||
let state: ProvidedState<T> = RefCell::new(ProvidedStateInner {
|
let state: ProvidedState<T> = RefCell::new(ProvidedStateInner {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use dioxus_core::{AnyContext, Scope};
|
use dioxus_core::ScopeState;
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
use std::{
|
use std::{
|
||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
@@ -7,10 +7,9 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn use_coroutine<'a, F: Future<Output = ()> + 'static>(
|
pub fn use_coroutine<'a, F: Future<Output = ()> + 'static>(
|
||||||
cx: &dyn AnyContext<'a>,
|
cx: &'a ScopeState,
|
||||||
mut f: impl FnMut() -> F + 'a,
|
mut f: impl FnMut() -> F + 'a,
|
||||||
) -> CoroutineHandle<'a> {
|
) -> CoroutineHandle<'a> {
|
||||||
let cx = cx.get_scope();
|
|
||||||
cx.use_hook(
|
cx.use_hook(
|
||||||
move |_| State {
|
move |_| State {
|
||||||
running: Default::default(),
|
running: Default::default(),
|
||||||
@@ -56,7 +55,7 @@ struct State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct CoroutineHandle<'a> {
|
pub struct CoroutineHandle<'a> {
|
||||||
cx: &'a Scope,
|
cx: &'a ScopeState,
|
||||||
inner: &'a State,
|
inner: &'a State,
|
||||||
}
|
}
|
||||||
impl Clone for CoroutineHandle<'_> {
|
impl Clone for CoroutineHandle<'_> {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
//!
|
//!
|
||||||
//! In these cases, we provide `use_model` - a convenient way of abstracting over some state and async functions.
|
//! In these cases, we provide `use_model` - a convenient way of abstracting over some state and async functions.
|
||||||
|
|
||||||
use dioxus_core::prelude::AnyContext;
|
use dioxus_core::prelude::ScopeState;
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
use std::{
|
use std::{
|
||||||
cell::{Cell, Ref, RefCell, RefMut},
|
cell::{Cell, Ref, RefCell, RefMut},
|
||||||
@@ -13,11 +13,7 @@ use std::{
|
|||||||
rc::Rc,
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn use_model<'a, T: 'static>(
|
pub fn use_model<'a, T: 'static>(cx: &'a ScopeState, f: impl FnOnce() -> T) -> UseModel<'a, T> {
|
||||||
cx: &dyn AnyContext<'a>,
|
|
||||||
f: impl FnOnce() -> T,
|
|
||||||
) -> UseModel<'a, T> {
|
|
||||||
let cx = cx.get_scope();
|
|
||||||
cx.use_hook(
|
cx.use_hook(
|
||||||
|_| UseModelInner {
|
|_| UseModelInner {
|
||||||
update_scheduled: Cell::new(false),
|
update_scheduled: Cell::new(false),
|
||||||
@@ -81,11 +77,10 @@ impl<'a, T: 'static> UseModel<'a, T> {
|
|||||||
|
|
||||||
// keep a coroutine going
|
// keep a coroutine going
|
||||||
pub fn use_model_coroutine<'a, T, F: Future<Output = ()> + 'static>(
|
pub fn use_model_coroutine<'a, T, F: Future<Output = ()> + 'static>(
|
||||||
cx: &dyn AnyContext<'a>,
|
cx: &'a ScopeState,
|
||||||
_model: UseModel<T>,
|
_model: UseModel<T>,
|
||||||
_f: impl FnOnce(AppModels) -> F,
|
_f: impl FnOnce(AppModels) -> F,
|
||||||
) -> UseModelCoroutine {
|
) -> UseModelCoroutine {
|
||||||
let cx = cx.get_scope();
|
|
||||||
cx.use_hook(
|
cx.use_hook(
|
||||||
|_| {
|
|_| {
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -3,10 +3,9 @@ use std::{
|
|||||||
rc::Rc,
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use dioxus_core::AnyContext;
|
use dioxus_core::ScopeState;
|
||||||
|
|
||||||
pub fn use_ref<'a, T: 'static>(cx: &dyn AnyContext<'a>, f: impl FnOnce() -> T) -> UseRef<'a, T> {
|
pub fn use_ref<'a, T: 'static>(cx: &'a ScopeState, f: impl FnOnce() -> T) -> UseRef<'a, T> {
|
||||||
let cx = cx.get_scope();
|
|
||||||
cx.use_hook(
|
cx.use_hook(
|
||||||
|_| UseRefInner {
|
|_| UseRefInner {
|
||||||
update_scheduled: Cell::new(false),
|
update_scheduled: Cell::new(false),
|
||||||
|
|||||||
@@ -50,10 +50,9 @@ use std::{
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn use_state<'a, T: 'static>(
|
pub fn use_state<'a, T: 'static>(
|
||||||
cx: &dyn AnyContext<'a>,
|
cx: &'a ScopeState,
|
||||||
initial_state_fn: impl FnOnce() -> T,
|
initial_state_fn: impl FnOnce() -> T,
|
||||||
) -> UseState<'a, T> {
|
) -> UseState<'a, T> {
|
||||||
let cx = cx.get_scope();
|
|
||||||
cx.use_hook(
|
cx.use_hook(
|
||||||
move |_| {
|
move |_| {
|
||||||
let first_val = initial_state_fn();
|
let first_val = initial_state_fn();
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ impl<R: Routable> RouterService<R> {
|
|||||||
/// This hould only be used once per app
|
/// This hould only be used once per app
|
||||||
///
|
///
|
||||||
/// You can manually parse the route if you want, but the derived `parse` method on `Routable` will also work just fine
|
/// You can manually parse the route if you want, but the derived `parse` method on `Routable` will also work just fine
|
||||||
pub fn use_router<R: Routable>(cx: Context, mut parse: impl FnMut(&str) -> R + 'static) -> &R {
|
pub fn use_router<R: Routable>(cx: Scope, mut parse: impl FnMut(&str) -> R + 'static) -> &R {
|
||||||
// for the web, attach to the history api
|
// for the web, attach to the history api
|
||||||
cx.use_hook(
|
cx.use_hook(
|
||||||
|f| {
|
|f| {
|
||||||
@@ -133,7 +133,7 @@ pub fn use_router<R: Routable>(cx: Context, mut parse: impl FnMut(&str) -> R + '
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn use_router_service<R: Routable>(cx: Context) -> Option<&Rc<RouterService<R>>> {
|
pub fn use_router_service<R: Routable>(cx: Scope) -> Option<&Rc<RouterService<R>>> {
|
||||||
cx.use_hook(|_| cx.consume_state::<RouterService<R>>(), |f| f.as_ref())
|
cx.use_hook(|_| cx.consume_state::<RouterService<R>>(), |f| f.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,7 +160,7 @@ pub struct LinkProps<R: Routable> {
|
|||||||
children: Element,
|
children: Element,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn Link<R: Routable>(cx: Context, props: &LinkProps<R>) -> Element {
|
pub fn Link<R: Routable>(cx: Scope, props: &LinkProps<R>) -> Element {
|
||||||
let service = use_router_service::<R>(cx)?;
|
let service = use_router_service::<R>(cx)?;
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
a {
|
a {
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ struct ActionButtonProps<'a> {
|
|||||||
onclick: &'a dyn Fn(),
|
onclick: &'a dyn Fn(),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ActionButton(cx: Context, props: &ActionButtonProps) -> Element {
|
fn ActionButton(cx: Scope, props: &ActionButtonProps) -> Element {
|
||||||
rsx!(cx, div { class: "col-sm-6 smallpad"
|
rsx!(cx, div { class: "col-sm-6 smallpad"
|
||||||
button { class:"btn btn-primary btn-block", r#type: "button", id: "{props.id}", onclick: move |_| (props.onclick)(),
|
button { class:"btn btn-primary btn-block", r#type: "button", id: "{props.id}", onclick: move |_| (props.onclick)(),
|
||||||
"{props.name}"
|
"{props.name}"
|
||||||
|
|||||||
Reference in new issue
Block a user