Feat: massive changes to definition of components

This change switches back to the original `ctx<props>` syntax for
commponents. This lets lifetime elision to remove the need to match
exactly which lifetime (props or ctx) gets  carried to the output. As
such, `Props` is currently required to be static. It *is* possible to
loosen this restriction, and will be done in the future, though only
through adding metadata about the props through the Props derive
macro. Implementing the IS_STATIC trait is unsafe, so the derive macro
will do it through some heuristics.

For now, this unlocks sharing vnodes from parents to children, enabling
pass-thru components, fragments, portals, etc.
This commit is contained in:
Jonathan Kelley committed 2021-06-01 18:33:15 -04:00
1 parent c1fd848f89
commit 508c560320
82 files changed
+692 -558

No files matched your search

+4 -5
View File
@@ -1,5 +1,5 @@
## Components
Dioxus should look and feel just like writing functional React components. In Dioxus, there are no class components with lifecycles. All state management is done via hooks. This encourages logic reusability and lessens the burden on Dioxus to maintain a non-breaking lifecycle API.
```rust
@@ -9,7 +9,7 @@ struct MyProps {
}
fn Example(ctx: Context<MyProps>) -> VNode {
html! { <div> "Hello {ctx.props.name}!" </div> }
html! { <div> "Hello {ctx.ctx.name}!" </div> }
}
```
@@ -25,8 +25,7 @@ fn Example(ctx: Context, name: String) -> VNode {
// or
#[functional_component]
static Example: FC = |ctx, name: String| html! { <div> "Hello {name}!" </div> };
static Example: FC = |ctx, name: String| html! { <div> "Hello {name}!" </div> };
```
The final output of components must be a tree of VNodes. We provide an html macro for using JSX-style syntax to write these, though, you could use any macro, DSL, templating engine, or the constructors directly.
The final output of components must be a tree of VNodes. We provide an html macro for using JSX-style syntax to write these, though, you could use any macro, DSL, templating engine, or the constructors directly.
+9 -11
View File
@@ -1,9 +1,9 @@
# Utilities
There are a few macros and utility functions that make life easier when writing Dioxus components.
There are a few macros and utility functions that make life easier when writing Dioxus components.
## The `functional_component` procedural macro
The `functional_component` proc macro allows you to inline props into the generic parameter of the component's context. This is useful When writing "pure" components, or when you don't want the extra clutter of structs, derives, and burden of naming things.
This macro allows allows a classic struct definition to be embedded directly into the function arguments. The props are automatically pulled from the context and destructured into the function's body, saving an extra step.
@@ -11,13 +11,13 @@ This macro allows allows a classic struct definition to be embedded directly int
```rust
// Inlines and destructure props *automatically*
#[functional_component]
fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> DomTree {
html! {
<div>
fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
html! {
<div>
<p> "Hello, {name}!" </p>
<p> "Status: {pending}!" </p>
<p> "Count {count}!" </p>
</div>
</div>
}
}
```
@@ -37,18 +37,16 @@ fn Example(ctx: &mut Context<ExampleProps>) -> VNode {
name, pending, count
} = ctx.props();
rsx! {
<div>
rsx! {
<div>
<p> "Hello, {name}!" </p>
<p> "Status: {pending}!" </p>
<p> "Count {count}!" </p>
</div>
</div>
}
}
```
## The rsx! macro
The rsx! macacro is similar to the html! macro in other libraries, but with a few add-ons to make it fun and easy to work with. We'll cover the rsx macro more in depth in the [vnode-macro](3-vnode-macros.md) chapter.
+13 -13
View File
@@ -1,39 +1,38 @@
# VNode Macros
Dioxus comes preloaded with two macros for creating VNodes.
Dioxus comes preloaded with two macros for creating VNodes.
## html! macro
The html! macro supports the html standard. This macro will happily accept a copy-paste from something like tailwind builder. Writing this one by hand is a bit tedious and doesn't come with much help from Rust IDE tools.
The html! macro supports the html standard. This macro will happily accept a copy-paste from something like tailwind builder. Writing this one by hand is a bit tedious and doesn't come with much help from Rust IDE tools.
There is also limited support for dynamic handlers, but it will function similarly to JSX.
```rust
#[fc]
fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> DomTree {
ctx.render(html! {
<div>
fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
ctx.render(html! {
<div>
<p> "Hello, {name}!" </p>
<p> "Status: {pending}!" </p>
<p> "Count {count}!" </p>
</div>
</div>
})
}
```
## rsx! macro
The rsx! macro is a VNode builder macro designed especially for Rust. Writing these should feel very natural, much like assembling a struct. VSCode also supports these with code folding, bracket-tabbing, bracket highlighting, and section selecting.
The rsx! macro is a VNode builder macro designed especially for Rust. Writing these should feel very natural, much like assembling a struct. VSCode also supports these with code folding, bracket-tabbing, bracket highlighting, and section selecting.
The Dioxus VSCode extension provides a function to convert a selection of html! template and turn it into rsx!, so you'll never need to transcribe templates by hand.
It's also a bit easier on the eyes 🙂.
It's also a bit easier on the eyes 🙂.
```rust
#[fc]
fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> DomTree {
ctx.render(rsx! {
fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
ctx.render(rsx! {
div {
p {"Hello, {name}!"}
p {"Status: {pending}!"}
@@ -45,16 +44,17 @@ fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> DomTree {
```
Each element takes a comma-separated list of expressions to build the node. Roughly, here's how they work:
- `name: value` sets the property on this element.
- `"text"` adds a new text element
- `tag {}` adds a new child element
- `tag {}` adds a new child element
- `CustomTag {}` adds a new child component
- `{expr}` pastes the `expr` tokens literally. They must be IntoCtx<Vnode> to work properly
Lists must include commas, much like how struct definitions work.
```rust
static Example: FC<()> = |ctx, props| {
static Example: FC<()> = |ctx| {
ctx.render(rsx!{
div {