Basic docs cleanups

This commit is contained in:
Jonathan Kelley committed 2024-03-27 17:06:10 -07:00
1 parent 41c3967052
commit a1c03a461d
3 files changed
+39 -97

No files matched your search

+3 -3
View File
@@ -104,7 +104,7 @@ pub fn component(_args: TokenStream, input: TokenStream) -> TokenStream {
/// ```rust,ignore
/// #[inline_props]
/// fn app(bob: String) -> Element {
/// rsx!("hello, {bob}"))
/// rsx! { "hello, {bob}") }
/// }
///
/// // is equivalent to
@@ -114,8 +114,8 @@ pub fn component(_args: TokenStream, input: TokenStream) -> TokenStream {
/// bob: String,
/// }
///
/// fn app(cx: Scope<AppProps>) -> Element {
/// rsx!("hello, {bob}"))
/// fn app(props: AppProps) -> Element {
/// rsx! { "hello, {bob}") }
/// }
/// ```
#[proc_macro_attribute]
+34 -92
View File
@@ -34,11 +34,11 @@ Remember: Dioxus is a library for declaring interactive user interfaces—it is
## Brief Overview
All Dioxus apps are built by composing functions that return an `Element`.
All Dioxus apps are built by composing functions that return an `Element`.
To launch an app, we use the `launch` method and use features in ``Cargo.toml`` to specify which renderer we want to use. In the launch function, we pass the app's root `Component`.
```rust, ignore
```rust
use dioxus::prelude::*;
fn main() {
@@ -49,7 +49,7 @@ fn main() {
// It's not required, but highly recommended. For example, UpperCamelCase components will not generate a warning.
#[component]
fn App() -> Element {
rsx!("hello world!")
rsx! { "hello world!" }
}
```
@@ -67,25 +67,25 @@ children.
```rust, ignore
let value = "123";
rsx!(
rsx! {
div {
class: "my-class {value}", // <--- attribute
onclick: move |_| info!("clicked!"), // <--- listener
h1 { "hello world" }, // <--- child
}
)
}
```
The `rsx!` macro accepts attributes in "struct form" and will parse the rest
of the body as child elements and rust expressions. Any rust expression that
implements `IntoIterator<Item = impl IntoVNode>` will be parsed as a child.
The `rsx!` macro accepts attributes in "struct form". Any rust expression contained within curly braces that implements `IntoIterator<Item = impl IntoVNode>` will be parsed as a child. We make two exceptions: both `for` loops and `if` statements are parsed where their body is parsed as a child.
```rust, ignore
rsx!(
rsx! {
div {
(0..10).map(|_| rsx!(span { "hello world" }))
for _ in 0..10 {
span { "hello world" }
}
}
)
}
```
The `rsx!` macro is what generates the `Element` that our components return.
@@ -93,7 +93,7 @@ The `rsx!` macro is what generates the `Element` that our components return.
```rust, ignore
#[component]
fn Example() -> Element {
rsx!("hello world")
rsx!{ "hello world" }
}
```
@@ -104,20 +104,14 @@ elements:
#[component]
fn App() -> Element {
let name = "dave";
rsx!(
rsx! {
h1 { "Hello, {name}!" }
div {
class: "my-class",
id: "my-id",
(0..5).map(|i| rsx!(
div { key: "{i}"
"FizzBuzz: {i}"
}
))
div { class: "my-class", id: "my-id",
for i in 0..5 {
div { "FizzBuzz: {i}" }
}
}
)
}
}
```
@@ -125,19 +119,19 @@ fn App() -> Element {
We can compose these function components to build a complex app. Each new
component we design must take some Properties. For components with no explicit
properties, we can use the `()` type or simply omit the type altogether.
properties we can omit the type altogether.
In Dioxus, all properties are memoized by default!
In Dioxus, all properties are memoized by default, and this implement both Clone and PartialEq. For props you can't clone, simply wrap the fields in a ReadOnlySignal and Dioxus will handle the wrapping for you.
```rust, ignore
#[component]
fn App() -> Element {
rsx!(
rsx! {
Header {
title: "My App",
color: "red",
}
)
}
}
```
@@ -154,12 +148,12 @@ struct HeaderProps {
#[component]
fn Header(props: HeaderProps) -> Element {
rsx!(
rsx! {
div {
background_color: "{props.color}"
h1 { "{props.title}" }
}
)
}
}
```
@@ -169,35 +163,12 @@ struct from function arguments:
```rust, ignore
#[component]
fn Header(title: String, color: String) -> Element {
rsx!(
rsx! {
div {
background_color: "{color}"
h1 { "{title}" }
}
)
}
```
Components may also borrow data from their parent component. We just need to
attach some lifetimes to the props struct.
> Note: we don't need to derive `PartialEq` for borrowed props since they cannot be memoized.
```rust, ignore
#[derive(Props)]
struct HeaderProps<'a> {
title: &'a str,
color: &'a str,
}
#[component]
fn Header<'a>(props: HeaderProps<'a>) -> Element {
rsx!(
div {
background_color: "{props.color}"
h1 { "{props.title}" }
}
)
}
}
```
@@ -205,23 +176,11 @@ Components that begin with an uppercase letter may be called with
the traditional (for React) curly-brace syntax like so:
```rust, ignore
rsx!(
rsx! {
Header { title: "My App" }
)
}
```
Alternatively, if your components begin with a lowercase letter, you can use
the function call syntax:
```rust, ignore
rsx!(
header( title: "My App" )
)
```
However, the convention is to use UpperCamelCase. The `#[component]` attribute will enforce this,
but you can turn it off if you wish.
## Hooks
While components are reusable forms of UI elements, hooks are reusable forms
@@ -236,7 +195,7 @@ use hooks to define the state and modify it from within listeners.
fn App() -> Element {
let name = use_signal(|| "world");
rsx!("hello {name}!")
rsx! { "hello {name}!" }
}
```
@@ -263,7 +222,7 @@ fn use_username(d: Uuid) -> bool {
To create entirely new foundational hooks, we can use the `use_hook` method.
```rust, ignore
fn use_mut_string() -> &mut String {
fn use_mut_string() -> String {
use_hook(|_| "Hello".to_string())
}
```
@@ -283,12 +242,12 @@ fn main() {
#[component]
fn App() -> Element {
let count = use_signal(|| 0);
let mut count = use_signal(|| 0);
rsx!(
div { "Count: {count}" }
button { onclick: move |_| count.set(count + 1), "Increment" }
button { onclick: move |_| count.set(count - 1), "Decrement" }
button { onclick: move |_| count += 1, "Increment" }
button { onclick: move |_| count -= 1, "Decrement" }
)
}
```
@@ -311,21 +270,4 @@ Beyond this overview, Dioxus supports:
- Basic fine-grained reactivity (IE SolidJS/Svelte)
- and more!
Good luck!
## Inspiration, Resources, Alternatives, and Credits
Dioxus is inspired by:
- React: for its hooks, concurrency, suspense
- Dodrio: for its research in bump allocation, double buffering, and diffing architecture
Alternatives to Dioxus include:
- Yew: supports function components and web, but no SSR, borrowed data, or bump allocation. Rather slow at times.
- Percy: supports function components, web, ssr, but lacks state management
- Sycamore: supports function components, web, ssr, but is closer to SolidJS than React
- MoonZoom/Seed: opinionated frameworks based on the Elm model (message, update)—no hooks
We've put a lot of work into making Dioxus ergonomic and _familiar_.
Our target audience is TypeScript developers looking to switch to Rust for the web—so we need to be comparable to React.
Build cool things ✌️
+2 -2
View File
@@ -110,7 +110,7 @@ impl<R, S: Storage<SignalData<bool>>> Copy for Comparer<R, S> {}
/// use dioxus::prelude::*;
/// use dioxus_signals::*;
///
/// fn App(cx: Scope) -> Element {
/// fn App() -> Element {
/// let mut count = use_signal(cx, || 0);
/// let comparer = use_comparer(cx, move || count.value());
///
@@ -129,7 +129,7 @@ impl<R, S: Storage<SignalData<bool>>> Copy for Comparer<R, S> {}
/// }
///
/// #[component]
/// fn Child(cx: Scope, active: ReadOnlySignal<bool>) -> Element {
/// fn Child(active: ReadOnlySignal<bool>) -> Element {
/// if *active() {
/// render! { "Active" }
/// } else {