Basic docs cleanups
This commit is contained in:
3 files changed
+38
-96
No files matched your search
@@ -104,7 +104,7 @@ pub fn component(_args: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
/// ```rust,ignore
|
/// ```rust,ignore
|
||||||
/// #[inline_props]
|
/// #[inline_props]
|
||||||
/// fn app(bob: String) -> Element {
|
/// fn app(bob: String) -> Element {
|
||||||
/// rsx!("hello, {bob}"))
|
/// rsx! { "hello, {bob}") }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// // is equivalent to
|
/// // is equivalent to
|
||||||
@@ -114,8 +114,8 @@ pub fn component(_args: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
/// bob: String,
|
/// bob: String,
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn app(cx: Scope<AppProps>) -> Element {
|
/// fn app(props: AppProps) -> Element {
|
||||||
/// rsx!("hello, {bob}"))
|
/// rsx! { "hello, {bob}") }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ 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`.
|
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::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@@ -49,7 +49,7 @@ fn main() {
|
|||||||
// It's not required, but highly recommended. For example, UpperCamelCase components will not generate a warning.
|
// It's not required, but highly recommended. For example, UpperCamelCase components will not generate a warning.
|
||||||
#[component]
|
#[component]
|
||||||
fn App() -> Element {
|
fn App() -> Element {
|
||||||
rsx!("hello world!")
|
rsx! { "hello world!" }
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -67,25 +67,25 @@ children.
|
|||||||
```rust, ignore
|
```rust, ignore
|
||||||
let value = "123";
|
let value = "123";
|
||||||
|
|
||||||
rsx!(
|
rsx! {
|
||||||
div {
|
div {
|
||||||
class: "my-class {value}", // <--- attribute
|
class: "my-class {value}", // <--- attribute
|
||||||
onclick: move |_| info!("clicked!"), // <--- listener
|
onclick: move |_| info!("clicked!"), // <--- listener
|
||||||
h1 { "hello world" }, // <--- child
|
h1 { "hello world" }, // <--- child
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The `rsx!` macro accepts attributes in "struct form" and will parse the rest
|
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.
|
||||||
of the body as child elements and rust expressions. Any rust expression that
|
|
||||||
implements `IntoIterator<Item = impl IntoVNode>` will be parsed as a child.
|
|
||||||
|
|
||||||
```rust, ignore
|
```rust, ignore
|
||||||
rsx!(
|
rsx! {
|
||||||
div {
|
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.
|
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
|
```rust, ignore
|
||||||
#[component]
|
#[component]
|
||||||
fn Example() -> Element {
|
fn Example() -> Element {
|
||||||
rsx!("hello world")
|
rsx!{ "hello world" }
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -104,20 +104,14 @@ elements:
|
|||||||
#[component]
|
#[component]
|
||||||
fn App() -> Element {
|
fn App() -> Element {
|
||||||
let name = "dave";
|
let name = "dave";
|
||||||
rsx!(
|
rsx! {
|
||||||
h1 { "Hello, {name}!" }
|
h1 { "Hello, {name}!" }
|
||||||
div {
|
div { class: "my-class", id: "my-id",
|
||||||
class: "my-class",
|
for i in 0..5 {
|
||||||
id: "my-id",
|
div { "FizzBuzz: {i}" }
|
||||||
|
}
|
||||||
(0..5).map(|i| rsx!(
|
|
||||||
div { key: "{i}"
|
|
||||||
"FizzBuzz: {i}"
|
|
||||||
}
|
|
||||||
))
|
|
||||||
|
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -125,19 +119,19 @@ fn App() -> Element {
|
|||||||
|
|
||||||
We can compose these function components to build a complex app. Each new
|
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
|
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
|
```rust, ignore
|
||||||
#[component]
|
#[component]
|
||||||
fn App() -> Element {
|
fn App() -> Element {
|
||||||
rsx!(
|
rsx! {
|
||||||
Header {
|
Header {
|
||||||
title: "My App",
|
title: "My App",
|
||||||
color: "red",
|
color: "red",
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -154,12 +148,12 @@ struct HeaderProps {
|
|||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
fn Header(props: HeaderProps) -> Element {
|
fn Header(props: HeaderProps) -> Element {
|
||||||
rsx!(
|
rsx! {
|
||||||
div {
|
div {
|
||||||
background_color: "{props.color}"
|
background_color: "{props.color}"
|
||||||
h1 { "{props.title}" }
|
h1 { "{props.title}" }
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -169,35 +163,12 @@ struct from function arguments:
|
|||||||
```rust, ignore
|
```rust, ignore
|
||||||
#[component]
|
#[component]
|
||||||
fn Header(title: String, color: String) -> Element {
|
fn Header(title: String, color: String) -> Element {
|
||||||
rsx!(
|
rsx! {
|
||||||
div {
|
div {
|
||||||
background_color: "{color}"
|
background_color: "{color}"
|
||||||
h1 { "{title}" }
|
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:
|
the traditional (for React) curly-brace syntax like so:
|
||||||
|
|
||||||
```rust, ignore
|
```rust, ignore
|
||||||
rsx!(
|
rsx! {
|
||||||
Header { title: "My App" }
|
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
|
## Hooks
|
||||||
|
|
||||||
While components are reusable forms of UI elements, hooks are reusable forms
|
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 {
|
fn App() -> Element {
|
||||||
let name = use_signal(|| "world");
|
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.
|
To create entirely new foundational hooks, we can use the `use_hook` method.
|
||||||
|
|
||||||
```rust, ignore
|
```rust, ignore
|
||||||
fn use_mut_string() -> &mut String {
|
fn use_mut_string() -> String {
|
||||||
use_hook(|_| "Hello".to_string())
|
use_hook(|_| "Hello".to_string())
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -283,12 +242,12 @@ fn main() {
|
|||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
fn App() -> Element {
|
fn App() -> Element {
|
||||||
let count = use_signal(|| 0);
|
let mut count = use_signal(|| 0);
|
||||||
|
|
||||||
rsx!(
|
rsx!(
|
||||||
div { "Count: {count}" }
|
div { "Count: {count}" }
|
||||||
button { onclick: move |_| count.set(count + 1), "Increment" }
|
button { onclick: move |_| count += 1, "Increment" }
|
||||||
button { onclick: move |_| count.set(count - 1), "Decrement" }
|
button { onclick: move |_| count -= 1, "Decrement" }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -311,21 +270,4 @@ Beyond this overview, Dioxus supports:
|
|||||||
- Basic fine-grained reactivity (IE SolidJS/Svelte)
|
- Basic fine-grained reactivity (IE SolidJS/Svelte)
|
||||||
- and more!
|
- and more!
|
||||||
|
|
||||||
Good luck!
|
Build cool things ✌️
|
||||||
|
|
||||||
## 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.
|
|
||||||
@@ -110,7 +110,7 @@ impl<R, S: Storage<SignalData<bool>>> Copy for Comparer<R, S> {}
|
|||||||
/// use dioxus::prelude::*;
|
/// use dioxus::prelude::*;
|
||||||
/// use dioxus_signals::*;
|
/// use dioxus_signals::*;
|
||||||
///
|
///
|
||||||
/// fn App(cx: Scope) -> Element {
|
/// fn App() -> Element {
|
||||||
/// let mut count = use_signal(cx, || 0);
|
/// let mut count = use_signal(cx, || 0);
|
||||||
/// let comparer = use_comparer(cx, move || count.value());
|
/// let comparer = use_comparer(cx, move || count.value());
|
||||||
///
|
///
|
||||||
@@ -129,7 +129,7 @@ impl<R, S: Storage<SignalData<bool>>> Copy for Comparer<R, S> {}
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// #[component]
|
/// #[component]
|
||||||
/// fn Child(cx: Scope, active: ReadOnlySignal<bool>) -> Element {
|
/// fn Child(active: ReadOnlySignal<bool>) -> Element {
|
||||||
/// if *active() {
|
/// if *active() {
|
||||||
/// render! { "Active" }
|
/// render! { "Active" }
|
||||||
/// } else {
|
/// } else {
|
||||||
|
|||||||
Reference in new issue
Block a user