diff --git a/README.md b/README.md index 9b0060b43..4be6f7cdc 100644 --- a/README.md +++ b/README.md @@ -199,6 +199,149 @@ You shouldn't use Dioxus if: - You want to support browsers where Wasm or asm.js are not supported. +## Show me some examples! + +In our collection of examples, guides, and tutorials, we have: +- The book (an introductory course) +- The guide (an in-depth analysis of everything in Dioxus) +- The reference (a collection of examples with heavy documentation) +- The general examples +- The platform-specific examples (web, ssr, desktop, mobile, server) + +Here's what a few common tasks look like in Dioxus: + +Nested components with children and internal state: +```rust +fn App(cx: Context, props: &()) -> Element { + cx.render(rsx!( Toggle { "Toggle me" } )) +} + +#[derive(PartialEq, Props)] +struct ToggleProps { children: Element } + +fn Toggle(cx: Context, props: &ToggleProps) -> Element { + let mut toggled = use_state(cx, || false); + cx.render(rsx!{ + div { + {&props.children} + button { onclick: move |_| toggled.set(true), + {toggled.and_then(|| "On").or_else(|| "Off")} + } + } + }) +} +``` + +Controlled inputs: +```rust +fn App(cx: Context, props: &()) -> Element { + let value = use_state(cx, String::new); + cx.render(rsx!( + input { + "type": "text", + value: "{value}", + oninput: move |evt| value.set(evt.value.clone()) + } + )) +} +``` + +Lists and Conditional rendering: +```rust +fn App(cx: Context, props: &()) -> Element { + let list = (0..10).map(|i| { + rsx!(li { key: "{i}", "Value: {i}" }) + }); + + let title = match list.len() { + 0 => rsx!("Not enough"), + _ => rsx!("Plenty!"), + }; + + if should_show { + cx.render(rsx!( + {title} + ul { {list} } + )) + } else { + None + } +} +``` + +Tiny components: +```rust +static App: FC<()> = |cx, _| rsx!(cx, div {"hello world!"}); +``` + +Borrowed prop contents: +```rust +fn App(cx: Context, props: &()) -> Element { + let name = use_state(cx, || String::from("example")); + rsx!(cx, Child { title: name.as_str() }) +} + +#[derive(Props)] +struct ChildProps<'a> { title: &'a str } + +fn Child(cx: Context, props: &ChildProps) -> Element { + rsx!(cx, "Hello {props.title}") +} +``` + +Global State +```rust +struct GlobalState { name: String } + +fn App(cx: Context, props: &()) -> Element { + use_provide_shared_state(cx, || GlobalState { name: String::from("Toby") }) + rsx!(cx, Leaf {}) +} + +fn Leaf(cx: Context, props: &()) -> Element { + let state = use_consume_shared_state::(cx)?; + rsx!(cx, "Hello {state.name}") +} +``` + +Router (inspired by Yew-Router) +```rust +#[derive(PartialEq, Clone, Hash, Eq, Routable)] +enum Route { + #[at("/")] + Home, + #[at("/post/{id}")] + Post(id) +} + +fn App(cx: Context, props: &()) -> Element { + let route = use_router(cx, Route::parse); + cx.render(rsx!(div { + {match route { + Route::Home => rsx!( Home {} ), + Route::Post(id) => rsx!( Post { id: id }) + }} + })) +} +``` + +Suspense +```rust +fn App(cx: Context, props: &()) -> Element { + let doggo = use_suspense(cx, + || async { reqwest::get("https://dog.ceo/api/breeds/image/random").await.unwrap().json::().await.unwrap() }, + |response| cx.render(rsx!( img { src: "{response.message}" })) + ); + + cx.render(rsx!{ + div { + "One doggo coming right up:" + {doggo} + } + }) +} +``` + ## License This project is licensed under the [MIT license]. diff --git a/packages/core/src/diff.rs b/packages/core/src/diff.rs index ba7eb30fd..2ec0564db 100644 --- a/packages/core/src/diff.rs +++ b/packages/core/src/diff.rs @@ -365,7 +365,6 @@ impl<'bump> DiffState<'bump> { fn create_text_node(&mut self, vtext: &'bump VText<'bump>, node: &'bump VNode<'bump>) { let real_id = self.scopes.reserve_node(node); - let parent = self.stack.element_stack.last().unwrap(); self.mutations.create_text_node(vtext.text, real_id); vtext.dom_id.set(Some(real_id)); @@ -413,7 +412,6 @@ impl<'bump> DiffState<'bump> { let real_id = self.scopes.reserve_node(node); self.stack.element_stack.push(real_id); dom_id.set(Some(real_id)); - log::debug!("Parent ID for {:?} set to {:?}", real_id, parent_id.get()); self.mutations.create_element(tag_name, *namespace, real_id); @@ -545,7 +543,7 @@ impl<'bump> DiffState<'bump> { &mut self, old: &'bump VText<'bump>, new: &'bump VText<'bump>, - old_node: &'bump VNode<'bump>, + _old_node: &'bump VNode<'bump>, new_node: &'bump VNode<'bump>, ) { if let Some(root) = old.dom_id.get() { diff --git a/packages/core/src/nodes.rs b/packages/core/src/nodes.rs index 865ff19c3..c43657158 100644 --- a/packages/core/src/nodes.rs +++ b/packages/core/src/nodes.rs @@ -261,9 +261,7 @@ pub struct VAnchor { /// A bump-allocated string slice and metadata. pub struct VText<'src> { pub text: &'src str, - pub dom_id: Cell>, - pub is_static: bool, } @@ -276,20 +274,12 @@ pub struct VFragment<'src> { /// An element like a "div" with children, listeners, and attributes. pub struct VElement<'a> { pub tag_name: &'static str, - pub namespace: Option<&'static str>, - pub key: Option<&'a str>, - pub dom_id: Cell>, - - // Keep the parent id around so we can bubble events through the tree pub parent_id: Cell>, - pub listeners: &'a [Listener<'a>], - pub attributes: &'a [Attribute<'a>], - pub children: &'a [VNode<'a>], } diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index 79cb68c06..452d31d7d 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -9,7 +9,6 @@ use fxhash::FxHashSet; use indexmap::IndexSet; use smallvec::SmallVec; use std::pin::Pin; -use std::rc::Rc; use std::sync::Arc; use std::task::Poll; use std::{any::Any, collections::VecDeque}; @@ -293,6 +292,7 @@ impl VirtualDom { let mut items = scope.items.borrow_mut(); + // really this should just be retain_mut but that doesn't exist yet while let Some(mut task) = items.tasks.pop() { // todo: does this make sense? // I don't usually write futures by hand @@ -312,9 +312,7 @@ impl VirtualDom { scopes_to_clear.push(*fut); } - for task in unfinished_tasks.drain(..) { - items.tasks.push(task); - } + items.tasks.extend(unfinished_tasks.drain(..)); } for scope in scopes_to_clear { @@ -461,17 +459,14 @@ impl VirtualDom { ); diff_state.stack.push(DiffInstruction::Diff { new, old }); diff_state.stack.scope_stack.push(scopeid); + let scope = scopes.get_scope(&scopeid).unwrap(); - let container = scope.container; - log::debug!("scope {:?} container {:?}", scope.our_arena_idx, container); - diff_state.stack.element_stack.push(container); + diff_state.stack.element_stack.push(scope.container); } } } - let work_completed = diff_state.work(&mut deadline); - - if work_completed { + if diff_state.work(&mut deadline) { let DiffState { mutations, seen_scopes,