Docs: more examples and docs

This commit is contained in:
Jonathan Kelley 2021-06-24 11:09:38 -04:00
parent 100a78f321
commit 7fbaf69cab
9 changed files with 177 additions and 54 deletions

View File

@ -89,3 +89,44 @@ TypeScript is a great addition to JavaScript, but comes with a lot of tweaking f
- various macros (`html!`, `rsx!`) for fast template iteration
And much more. Dioxus makes Rust apps just as fast to write as React apps, but affords more robustness, giving your frontend team greater confidence in making big changes in shorter time. Dioxus also works on the server, on the web, on mobile, on desktop - and it runs completely natively so performance is never an issue.
# Parity with React
Sorted by priority
| Feature | Dioxus | React | Notes |
| ---------------------- | ------ | ----- | ------------------------------------------------ |
| ----- Phase 1 ----- | ----- | ----- | ----- |
| Conditional Rendering | ✅ | ✅ | if/then to hide/show component |
| Map, Iterator | ✅ | ✅ | map/filter/reduce rsx! |
| Keyed Components | ✅ | ✅ | advanced diffing with keys |
| Web | ✅ | ✅ | renderer for web browser |
| Desktop (webview) | ✅ | ✅ | renderer for desktop |
| Context | ✅ | ✅ | share state through the tree |
| Hook | ✅ | ✅ | memory cells in components |
| SSR | ✅ | ✅ | render directly to string |
| Runs natively | ✅ | 👀 | runs as a portable binary w/o a runtime (Node) |
| Component Children | ✅ | ✅ | cx.children() as a list of nodes |
| Null components | ✅ | ✅ | allow returning no components |
| No-div components | ✅ | ✅ | components that render components |
| Fragments | ✅ | ✅ | rsx! can return multiple elements without a root |
| Manual Props | 👀 | ✅ | Manually pass in props |
| NodeRef | 👀 | ✅ | gain direct access to nodes |
| Controlled Inputs | ✅ | ✅ | stateful wrappers around inputs |
| CSS/Inline Styles | 🛠 | ✅ | syntax for inline/conditional styles |
| 1st class global state | 🛠 | ✅ | redux/recoil/mobx on top of context |
| ----- Phase 2 ----- | ----- | ----- | ----- |
| 1st class router | 👀 | ✅ | Hook built on top of history |
| Assets | 👀 | ✅ | include css/svg/img url statically |
| Integrated classnames | 🛠 | 👀 | built-in `classnames` |
| Suspense | 👀 | 👀 | schedule future render from future/promise |
| Transition | 👀 | 👀 | High-level control over suspense |
| Animation | 👀 | ✅ | Spring-style animations |
| Mobile | 👀 | ✅ | Render with cacao |
| Desktop (native) | 👀 | ✅ | Render with native desktop |
| 3D Renderer | 👀 | ✅ | react-three-fiber |
| ----- Phase 3 ----- | ----- | ----- | ----- |
| Portal | 👀 | ✅ | cast elements through tree |
| Error/Panic boundary | 👀 | ✅ | catch panics and display custom BSOD |
| Code-splitting | 👀 | ✅ | Make bundle smaller/lazy |
| LiveView | 👀 | 👀 | Example for SSR + WASM apps |

View File

@ -2,13 +2,7 @@
use dioxus_core::prelude::*;
fn main() {
Some(10)
.map(|f| f * 5)
.map(|f| f / 3)
.map(|f| f * 5)
.map(|f| f / 3);
}
fn main() {}
static Example: FC<()> = |ctx| {
let (name, set_name) = use_state(&ctx, || "...?");

View File

@ -5,10 +5,6 @@
//!
//! A full in-depth reference guide is available at: https://www.notion.so/rsx-macro-basics-ef6e367dec124f4784e736d91b0d0b19
//!
//! ## Topics
//!
//!
//!
//! ### Elements
//! - Create any element from its tag
//! - Accept compile-safe attributes for each tag
@ -46,23 +42,119 @@ fn main() {
dioxus::webview::launch(Example);
}
/// When trying to return "nothing" to Dioxus, you'll need to specify the type parameter or Rust will be sad.
/// This type alias specifices the type for you so you don't need to write "None as Option<()>"
const NONE_ELEMENT: Option<()> = None;
use baller::Baller;
use dioxus_core::prelude::*;
static Example: FC<()> = |ctx| {
ctx.render(rsx! {
static Example: FC<()> = |cx| {
let formatting = "formatting!";
let formatting_tuple = ("a", "b");
let lazy_fmt = format_args!("lazily formatted text");
cx.render(rsx! {
div {
// Elements
div {}
h1 {"Some text"}
h1 {"Some text with {formatting}"}
h1 {"Formatting basic expressions {formatting_tuple.0} and {formatting_tuple.1}"}
h2 {
"Multiple"
"Text"
"Blocks"
"Use comments as separators in html"
}
div {
h1 {"multiple"}
h2 {"nested"}
h3 {"elements"}
}
div {
class: "my special div"
h1 {"Headers and attributes!"}
}
div {
// pass simple rust expressions in
class: lazy_fmt,
id: format_args!("attributes can be passed lazily with std::fmt::Arguments"),
div {
class: {
const WORD: &str = "expressions";
format_args!("Arguments can be passed in through curly braces for complex {}", WORD)
}
}
}
// Expressions can be used in element position too:
{rsx!(p { "More templating!" })}
{html!(<p>"Even HTML templating!!"</p>)}
// Iterators
{(0..10).map(|i| rsx!(li { "{i}" }))}
{{
let data = std::collections::HashMap::<&'static str, &'static str>::new();
// Iterators *should* have keys when you can provide them.
// Keys make your app run faster. Make sure your keys are stable, unique, and predictable.
// Using an "ID" associated with your data is a good idea.
data.into_iter().map(|(k, v)| rsx!(li { key: "{k}" "{v}" }))
}}
// Matching
// Matching will throw a Rust error about "no two closures are the same type"
// To fix this, call "render" method or use the "in" syntax to produce VNodes.
// There's nothing we can do about it, sorry :/ (unless you want *really* unhygenic macros)
{match true {
true => rsx!(in cx, h1 {"Top text"}),
false => cx.render(rsx!( h1 {"Bottom text"}))
}}
// ==============
// Components
// ==============
// Conditional rendering
// Dioxus conditional rendering is based around None/Some. We have no special syntax for conditionals.
// You can convert a bool condition to rsx! with .then and .or
{true.then(|| rsx!(div {}))}
// True conditions need to be rendered (same reasons as matching)
{if true {
rsx!(in cx, h1 {"Top text"})
} else {
cx.render(rsx!( h1 {"Bottom text"}))
}}
// returning "None" is a bit noisy... but rare in practice
{None as Option<()>}
// Use the Dioxus type-alias for less noise
{NONE_ELEMENT}
// can also just use empty fragments
Fragment {}
// Fragments let you insert groups of nodes without a parent.
// This lets you make components that insert elements as siblings without a container.
div {"A"}
Fragment {
div {"B"}
div {"C"}
Fragment {
"D"
Fragment {
"heavily nested fragments is an antipattern"
"they cause Dioxus to do unnecessary work"
"don't use them carelessly if you can help it"
}
}
}
// Components
// Can accept any paths
crate::baller::Baller {}
// Notice how you still get syntax highlighting and IDE support :)
Baller {}
baller::Baller { }
crate::baller::Baller {}
// Can take properties
Taller { a: "asd" }
@ -71,10 +163,14 @@ static Example: FC<()> = |ctx| {
Taller { a: "asd" }
// Can pass in props directly
Taller { a: "asd" /* ..{props}*/ }
{{
todo!("this neesd to be implemented");
let props = TallerProps {a: "hello"};
rsx!(Taller {a: "a"})
}}
// Can take children
Taller { a: "asd", div {} }
Taller { a: "asd", div {"hello world!"} }
}
})
};
@ -83,7 +179,8 @@ mod baller {
use super::*;
pub struct BallerProps {}
pub fn Baller(ctx: Context<()>) -> VNode {
/// This component totally balls
pub fn Baller(cx: Context<()>) -> VNode {
todo!()
}
}
@ -93,6 +190,7 @@ pub struct TallerProps {
a: &'static str,
}
/// This component is taller than most :)
pub fn Taller(ctx: Context<TallerProps>) -> VNode {
let b = true;
todo!()

View File

@ -6,22 +6,26 @@
//! Under the hood, the dioxus_webview crate bridges a native Dioxus VirtualDom with a custom prebuit application running
//! in the webview runtime. Custom handlers are provided for the webview instance to consume patches and emit user events
//! into the native VDom instance.
//!
//! Currently, NodeRefs won't work properly, but all other event functionality will.
use dioxus::prelude::*;
fn main() {
dioxus::webview::launch(|ctx| {
let (count, set_count) = use_state(&ctx, || 0);
ctx.render(rsx! {
div {
h1 { "Dioxus Desktop Demo" }
p { "Count is {count}" }
button {
"Click to increment"
onclick: |_| set_count(count + 1)
}
}
})
});
dioxus::webview::launch(App);
}
static App: FC<()> = |cx| {
let (count, set_count) = use_state(&cx, || 0);
cx.render(rsx! {
div {
h1 { "Dioxus Desktop Demo" }
p { "Count is {count}" }
button {
"Click to increment"
onclick: move |_| set_count(count + 1)
}
}
})
};

View File

@ -13,11 +13,12 @@ Sorted by priority
| Context | ✅ | ✅ | share state through the tree |
| Hook | ✅ | ✅ | memory cells in components |
| SSR | ✅ | ✅ | render directly to string |
| Runs natively | ✅ | 👀 | runs as a portable binary w/ extra tooling |
| Runs natively | ✅ | 👀 | runs as a portable binary w/o a runtime (Node) |
| Component Children | ✅ | ✅ | cx.children() as a list of nodes |
| Null components | ✅ | ✅ | allow returning no components |
| No-div components | ✅ | ✅ | components that render components |
| Fragments | ✅ | ✅ | rsx! can return multiple elements without a root |
| Manual Props | 👀 | ✅ | Manually pass in props |
| NodeRef | 👀 | ✅ | gain direct access to nodes |
| Controlled Inputs | ✅ | ✅ | stateful wrappers around inputs |
| CSS/Inline Styles | 🛠 | ✅ | syntax for inline/conditional styles |

View File

@ -778,7 +778,7 @@ Any function prefixed with "use" should not be called conditionally.
}
/// There are hooks going on here!
fn use_context<T: 'static>(&self) -> &'src Rc<T> {
fn use_context<T: 'static>(&self) -> &'src T {
self.try_use_context().unwrap()
}

View File

@ -23,21 +23,15 @@ wasm-bindgen-test = "0.3.21"
once_cell = "1.7.2"
atoms = { path="../atoms" }
# wasm-bindgen = "0.2.70"
# futures = "0.3.12"
# html-validation = { path = "../html-validation", version = "0.1.1" }
async-channel = "1.6.1"
nohash-hasher = "0.2.0"
anyhow = "1.0.41"
# futures-lite = "1.11.3"
[dependencies.web-sys]
version = "0.3.50"
features = [
"Comment",
"Document",
# "DataTransfer",
"Element",
"HtmlElement",
"HtmlInputElement",
@ -64,18 +58,12 @@ features = [
"DocumentType",
"CharacterData",
"HtmlOptionElement",
]
[profile.release]
lto = true
opt-level = 's'
# debug = true
# [profile.release]
[lib]
crate-type = ["cdylib", "rlib"]
@ -83,7 +71,3 @@ crate-type = ["cdylib", "rlib"]
im-rc = "15.0.0"
rand = { version="0.8.4", features=["small_rng"] }
uuid = { version="0.8.2", features=["v4", "wasm-bindgen"] }
[[example]]
name = "todomvc"
path = "./examples/todomvc/main.rs"

View File

@ -12,6 +12,7 @@
//!
use dioxus_core::prelude::*;
use dioxus_core as dioxus;
use dioxus_web::WebsysRenderer;
fn main() {

View File

@ -231,6 +231,6 @@ pub mod atoms {}
// #[cfg(feature = "desktop")]
pub mod webview {
//! A webview based renderer for building desktop applications with Dioxus
use dioxus_core::prelude::FC;
pub fn launch<P>(f: FC<P>) {}
use dioxus_core::prelude::{Properties, FC};
pub fn launch<P: Properties>(f: FC<P>) {}
}