Update Docs CI with mdbook translation support (#516)
* Update Docs CI with mdbook translation support #514 * install mdbook with --rev
This commit is contained in:
1 parent
df5338f4e6
commit
9538cfe733
37 files changed
+151
-145
No files matched your search
@@ -4,7 +4,7 @@
|
||||
Instead of passing a closure, you can also pass a string to event handlers – this lets you use JavaScript (if your renderer can execute JavaScript):
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/event_javascript.rs:rsx}}
|
||||
{{#include ../../../examples/event_javascript.rs:rsx}}
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
The `use_future` and `use_coroutine` hooks are useful if you want to unconditionally spawn the future. Sometimes, though, you'll want to only spawn a future in response to an event, such as a mouse click. For example, suppose you need to send a request when the user clicks a "log in" button. For this, you can use `cx.spawn`:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/spawn.rs:spawn}}
|
||||
{{#include ../../../examples/spawn.rs:spawn}}
|
||||
```
|
||||
|
||||
> Note: `spawn` will always spawn a *new* future. You most likely don't want to call it on every render.
|
||||
@@ -15,7 +15,7 @@ However, since you'll typically need a way to update the value of a hook, you ca
|
||||
To make this a bit less verbose, Dioxus exports the `to_owned!` macro which will create a binding as shown above, which can be quite helpful when dealing with many values.
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/spawn.rs:to_owned_macro}}
|
||||
{{#include ../../../examples/spawn.rs:to_owned_macro}}
|
||||
```
|
||||
|
||||
Calling `spawn` will give you a `JoinHandle` which lets you cancel or pause the future.
|
||||
@@ -25,5 +25,5 @@ Calling `spawn` will give you a `JoinHandle` which lets you cancel or pause the
|
||||
Sometimes, you might want to spawn a background task that needs multiple threads or talk to hardware that might block your app code. In these cases, we can directly spawn a Tokio task from our future. For Dioxus-Desktop, your task will be spawned onto Tokio's Multithreaded runtime:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/spawn.rs:tokio}}
|
||||
{{#include ../../../examples/spawn.rs:tokio}}
|
||||
```
|
||||
@@ -5,7 +5,7 @@
|
||||
For example, we can make an API request inside `use_future`:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/use_future.rs:use_future}}
|
||||
{{#include ../../../examples/use_future.rs:use_future}}
|
||||
```
|
||||
|
||||
The code inside `use_future` will be submitted to the Dioxus scheduler once the component has rendered.
|
||||
@@ -15,7 +15,7 @@ We can use `.value()` to get the result of the future. On the first run, since t
|
||||
We can then render that result:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/use_future.rs:render}}
|
||||
{{#include ../../../examples/use_future.rs:render}}
|
||||
```
|
||||
|
||||
|
||||
@@ -29,5 +29,5 @@ Often, you will need to run the future again every time some value (e.g. a prop)
|
||||
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/use_future.rs:dependency}}
|
||||
{{#include ../../../examples/use_future.rs:dependency}}
|
||||
```
|
||||
@@ -9,7 +9,7 @@ Fragments don't mount a physical element to the DOM immediately, so Dioxus must
|
||||
Only Component and Fragment nodes are susceptible to this issue. Dioxus mitigates this with components by providing an API for registering shared state without the Context Provider pattern.
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/anti_patterns.rs:nested_fragments}}
|
||||
{{#include ../../../examples/anti_patterns.rs:nested_fragments}}
|
||||
```
|
||||
|
||||
## Incorrect Iterator Keys
|
||||
@@ -17,7 +17,7 @@ Only Component and Fragment nodes are susceptible to this issue. Dioxus mitigate
|
||||
As described in the conditional rendering chapter, list items must have unique keys that are associated with the same items across renders. This helps Dioxus associate state with the contained components, and ensures good diffing performance. Do not omit keys, unless you know that the list is static and will never change.
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/anti_patterns.rs:iter_keys}}
|
||||
{{#include ../../../examples/anti_patterns.rs:iter_keys}}
|
||||
```
|
||||
|
||||
## Avoid Interior Mutability in Props
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
In some cases, you may wish to create a component that acts as a container for some other content, without the component needing to know what that content is. To achieve this, create a prop of type `Element`:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/component_element_props.rs:Clickable}}
|
||||
{{#include ../../../examples/component_element_props.rs:Clickable}}
|
||||
```
|
||||
|
||||
Then, when rendering the component, you can pass in the output of `cx.render(rsx!(...))`:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/component_element_props.rs:Clickable_usage}}
|
||||
{{#include ../../../examples/component_element_props.rs:Clickable_usage}}
|
||||
```
|
||||
|
||||
> Note: Since `Element<'a>` is a borrowed prop, there will be no memoization.
|
||||
@@ -21,11 +21,11 @@ Then, when rendering the component, you can pass in the output of `cx.render(rsx
|
||||
Rather than passing the RSX through a regular prop, you may wish to accept children similarly to how elements can have children. The "magic" `children` prop lets you achieve this:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/component_children.rs:Clickable}}
|
||||
{{#include ../../../examples/component_children.rs:Clickable}}
|
||||
```
|
||||
|
||||
This makes using the component much simpler: simply put the RSX inside the `{}` brackets – and there is no need for a `render` call or another macro!
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/component_children.rs:Clickable_usage}}
|
||||
{{#include ../../../examples/component_children.rs:Clickable_usage}}
|
||||
```
|
||||
@@ -20,12 +20,12 @@ There are 2 flavors of Props structs:
|
||||
Owned Props are very simple – they don't borrow anything. Example:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/component_owned_props.rs:Likes}}
|
||||
{{#include ../../../examples/component_owned_props.rs:Likes}}
|
||||
```
|
||||
|
||||
You can then pass prop values to the component the same way you would pass attributes to an element:
|
||||
```rust
|
||||
{{#include ../../examples/component_owned_props.rs:App}}
|
||||
{{#include ../../../examples/component_owned_props.rs:App}}
|
||||
```
|
||||
|
||||

|
||||
@@ -37,13 +37,13 @@ Owning props works well if your props are easy to copy around – like a single
|
||||
Rust allows for something more efficient – borrowing the String as a `&str` – this is what Borrowed Props are for!
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/component_borrowed_props.rs:TitleCard}}
|
||||
{{#include ../../../examples/component_borrowed_props.rs:TitleCard}}
|
||||
```
|
||||
|
||||
We can then use the component like this:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/component_borrowed_props.rs:App}}
|
||||
{{#include ../../../examples/component_borrowed_props.rs:App}}
|
||||
```
|
||||

|
||||
|
||||
@@ -57,13 +57,13 @@ The `#[derive(Props)]` macro has some features that let you customize the behavi
|
||||
You can create optional fields by using the `Option<…>` type for a field:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/component_props_options.rs:OptionalProps}}
|
||||
{{#include ../../../examples/component_props_options.rs:OptionalProps}}
|
||||
```
|
||||
|
||||
Then, you can choose to either provide them or not:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/component_props_options.rs:OptionalProps_usage}}
|
||||
{{#include ../../../examples/component_props_options.rs:OptionalProps_usage}}
|
||||
```
|
||||
|
||||
### Explicitly Required `Option`s
|
||||
@@ -71,13 +71,13 @@ Then, you can choose to either provide them or not:
|
||||
If you want to explicitly require an `Option`, and not an optional prop, you can annotate it with `#[props(!optional)]`:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/component_props_options.rs:ExplicitOption}}
|
||||
{{#include ../../../examples/component_props_options.rs:ExplicitOption}}
|
||||
```
|
||||
|
||||
Then, you have to explicitly pass either `Some("str")` or `None`:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/component_props_options.rs:ExplicitOption_usage}}
|
||||
{{#include ../../../examples/component_props_options.rs:ExplicitOption_usage}}
|
||||
```
|
||||
|
||||
### Default Props
|
||||
@@ -85,13 +85,13 @@ Then, you have to explicitly pass either `Some("str")` or `None`:
|
||||
You can use `#[props(default = 42)]` to make a field optional and specify its default value:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/component_props_options.rs:DefaultComponent}}
|
||||
{{#include ../../../examples/component_props_options.rs:DefaultComponent}}
|
||||
```
|
||||
|
||||
Then, similarly to optional props, you don't have to provide it:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/component_props_options.rs:DefaultComponent_usage}}
|
||||
{{#include ../../../examples/component_props_options.rs:DefaultComponent_usage}}
|
||||
```
|
||||
|
||||
### Automatic Conversion with `.into`
|
||||
@@ -99,13 +99,13 @@ Then, similarly to optional props, you don't have to provide it:
|
||||
It is common for Rust functions to accept `impl Into<SomeType>` rather than just `SomeType` to support a wider range of parameters. If you want similar functionality with props, you can use `#[props(into)]`. For example, you could add it on a `String` prop – and `&str` will also be automatically accepted, as it can be converted into `String`:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/component_props_options.rs:IntoComponent}}
|
||||
{{#include ../../../examples/component_props_options.rs:IntoComponent}}
|
||||
```
|
||||
|
||||
Then, you can use it so:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/component_props_options.rs:IntoComponent_usage}}
|
||||
{{#include ../../../examples/component_props_options.rs:IntoComponent_usage}}
|
||||
```
|
||||
|
||||
## The `inline_props` macro
|
||||
|
||||
@@ -5,7 +5,7 @@ Just like you wouldn't want to write a complex program in a single, long, `main`
|
||||
A component is a Rust function, named in UpperCammelCase, that takes a `Scope` parameter and returns an `Element` describing the UI it wants to render. In fact, our `App` function is a component!
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/hello_world_desktop.rs:component}}
|
||||
{{#include ../../../examples/hello_world_desktop.rs:component}}
|
||||
```
|
||||
|
||||
> You'll probably want to add `#![allow(non_snake_case)]` to the top of your crate to avoid warnings about the function name
|
||||
@@ -13,13 +13,13 @@ A component is a Rust function, named in UpperCammelCase, that takes a `Scope` p
|
||||
A Component is responsible for some rendering task – typically, rendering an isolated part of the user interface. For example, you could have an `About` component that renders a short description of Dioxus Labs:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/components.rs:About}}
|
||||
{{#include ../../../examples/components.rs:About}}
|
||||
```
|
||||
|
||||
Then, you can render your component in another component, similarly to how elements are rendered:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/components.rs:App}}
|
||||
{{#include ../../../examples/components.rs:App}}
|
||||
```
|
||||
|
||||

|
||||
|
||||
@@ -5,7 +5,7 @@ Dioxus is a *declarative* framework. This means that instead of telling Dioxus w
|
||||
You have already seen a simple example or RSX syntax in the "hello world" application:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/hello_world_desktop.rs:component}}
|
||||
{{#include ../../../examples/hello_world_desktop.rs:component}}
|
||||
```
|
||||
|
||||
Here, we use the `rsx!` macro to *declare* that we want a `div` element, containing the text `"Hello, world!"`. Dioxus takes the RSX and constructs a UI from it.
|
||||
@@ -15,7 +15,7 @@ Here, we use the `rsx!` macro to *declare* that we want a `div` element, contain
|
||||
RSX is very similar to HTML in that it describes elements with attributes and children. Here's an empty `div` element in RSX, as well as the resulting HTML:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/rsx_overview.rs:empty}}
|
||||
{{#include ../../../examples/rsx_overview.rs:empty}}
|
||||
```
|
||||
```html
|
||||
<div></div>
|
||||
@@ -23,10 +23,10 @@ RSX is very similar to HTML in that it describes elements with attributes and ch
|
||||
|
||||
### Children
|
||||
|
||||
To add children to an element, put them inside the `{}` brackets. They can be either other elements, or text. For example, you could have an `ol` (ordered list) element, containing 3 `li` (list item) elements, each of which contains some text:
|
||||
To add children to an element, put them inside the `{}` brackets. They can be either other elements, or text. For example, you could have an `ol` (ordered list) element, containing 3 `li` (list item) elements, each of which contains some text:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/rsx_overview.rs:children}}
|
||||
{{#include ../../../examples/rsx_overview.rs:children}}
|
||||
```
|
||||
```html
|
||||
<ol>
|
||||
@@ -43,7 +43,7 @@ You can also "group" elements by wrapping them in `Fragment {}`. This will not c
|
||||
> Note: you can also render multiple elements at the top level of `rsx!` and they will be automatically grouped – no need for an explicit `Fragment {}` there.
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/rsx_overview.rs:fragments}}
|
||||
{{#include ../../../examples/rsx_overview.rs:fragments}}
|
||||
```
|
||||
|
||||
```html
|
||||
@@ -58,7 +58,7 @@ You can also "group" elements by wrapping them in `Fragment {}`. This will not c
|
||||
|
||||
Attributes are also specified inside the `{}` brackets, using the `name: value` syntax. You can provide the value as a literal in the RSX:
|
||||
```rust
|
||||
{{#include ../../examples/rsx_overview.rs:attributes}}
|
||||
{{#include ../../../examples/rsx_overview.rs:attributes}}
|
||||
```
|
||||
```html
|
||||
<a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ" class="primary_button" autofocus="true">Log In</a>
|
||||
@@ -71,7 +71,7 @@ Attributes are also specified inside the `{}` brackets, using the `name: value`
|
||||
Dioxus has a pre-configured set of attributes that you can use. RSX is validated at compile time to make sure you didn't specify an invalid attribute. If you want to override this behavior with a custom attribute name, specify the attribute in quotes:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/rsx_overview.rs:custom_attributes}}
|
||||
{{#include ../../../examples/rsx_overview.rs:custom_attributes}}
|
||||
```
|
||||
```html
|
||||
<b customAttribute="value">
|
||||
@@ -84,7 +84,7 @@ Dioxus has a pre-configured set of attributes that you can use. RSX is validated
|
||||
Similarly to how you can [format](https://doc.rust-lang.org/rust-by-example/hello/print/fmt.html) Rust strings, you can also interpolate in RSX text. Use `{variable}` to Display the value of a variable in a string, or `{variable:?}` to use the Debug representation:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/rsx_overview.rs:formatting}}
|
||||
{{#include ../../../examples/rsx_overview.rs:formatting}}
|
||||
```
|
||||
```html
|
||||
|
||||
@@ -99,7 +99,7 @@ Similarly to how you can [format](https://doc.rust-lang.org/rust-by-example/hell
|
||||
You can include arbitrary Rust expressions within RSX, but you must escape them in `[]` brackets:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/rsx_overview.rs:expression}}
|
||||
{{#include ../../../examples/rsx_overview.rs:expression}}
|
||||
```
|
||||
```html
|
||||
<span>DIOXUS</span>
|
||||
|
||||
@@ -10,7 +10,7 @@ For example, shipping a markdown-to-Dioxus converter might significantly bloat y
|
||||
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/dangerous_inner_html.rs:dangerous_inner_html}}
|
||||
{{#include ../../../examples/dangerous_inner_html.rs:dangerous_inner_html}}
|
||||
```
|
||||
|
||||
> Note! This attribute is called "dangerous_inner_html" because it is **dangerous** to pass it data you don't trust. If you're not careful, you can easily expose [cross-site scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) attacks to your users.
|
||||
@@ -25,7 +25,7 @@ Most attributes, when rendered, will be rendered exactly as the input you provid
|
||||
So this RSX wouldn't actually render the `hidden` attribute:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/boolean_attribute.rs:boolean_attribute}}
|
||||
{{#include ../../../examples/boolean_attribute.rs:boolean_attribute}}
|
||||
```
|
||||
```html
|
||||
<div>hello</div>
|
||||
|
||||
@@ -41,5 +41,5 @@ cargo add dioxus --features desktop
|
||||
Edit your `main.rs`:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/hello_world_desktop.rs:all}}
|
||||
{{#include ../../../examples/hello_world_desktop.rs:all}}
|
||||
```
|
||||
@@ -21,10 +21,10 @@ cd demo
|
||||
cargo add dioxus --features tui
|
||||
```
|
||||
|
||||
Then, edit your `main.rs` with the basic template.
|
||||
Then, edit your `main.rs` with the basic template.
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/hello_world_tui.rs}}
|
||||
{{#include ../../../examples/hello_world_tui.rs}}
|
||||
```
|
||||
|
||||
To run our app:
|
||||
@@ -36,7 +36,7 @@ cargo run
|
||||
Press "ctrl-c" to close the app. To switch from "ctrl-c" to just "q" to quit you can launch the app with a configuration to disable the default quit and use the root TuiContext to quit on your own.
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/hello_world_tui_no_ctrl_c.rs}}
|
||||
{{#include ../../../examples/hello_world_tui_no_ctrl_c.rs}}
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
@@ -61,7 +61,7 @@ Add an `index.html` for Trunk to use. Make sure your "mount point" element has a
|
||||
|
||||
Edit your `main.rs`:
|
||||
```rust
|
||||
{{#include ../../examples/hello_world_web.rs}}
|
||||
{{#include ../../../examples/hello_world_web.rs}}
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ To avoid repetition, you can encapsulate business logic based on existing hooks
|
||||
For example, if many components need to access an `AppSettings` struct, you can create a "shortcut" hook:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/hooks_composed.rs:wrap_context}}
|
||||
{{#include ../../../examples/hooks_composed.rs:wrap_context}}
|
||||
```
|
||||
|
||||
## Custom Hook Logic
|
||||
|
||||
@@ -7,7 +7,7 @@ Sometimes you want to render different things depending on the state/props. With
|
||||
To render different elements based on a condition, you could use an `if-else` statement:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/conditional_rendering.rs:if_else}}
|
||||
{{#include ../../../examples/conditional_rendering.rs:if_else}}
|
||||
```
|
||||
|
||||
> You could also use `match` statements, or any Rust function to conditionally render different things.
|
||||
@@ -18,7 +18,7 @@ To render different elements based on a condition, you could use an `if-else` st
|
||||
Since `Element` is a `Option<VNode>`, components accepting `Element` as a prop can actually inspect its contents, and render different things based on that. Example:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/component_children_inspect.rs:Clickable}}
|
||||
{{#include ../../../examples/component_children_inspect.rs:Clickable}}
|
||||
```
|
||||
|
||||
You can't mutate the `Element`, but if you need a modified version of it, you can construct a new one based on its attributes/children/etc.
|
||||
@@ -29,7 +29,7 @@ You can't mutate the `Element`, but if you need a modified version of it, you ca
|
||||
To render nothing, you can return `None` from a component. This is useful if you want to conditionally hide something:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/conditional_rendering.rs:conditional_none}}
|
||||
{{#include ../../../examples/conditional_rendering.rs:conditional_none}}
|
||||
```
|
||||
|
||||
This works because the `Element` type is just an alias for `Option<VNode>`
|
||||
@@ -50,7 +50,7 @@ For this, Dioxus accepts iterators that produce `Element`s. So we need to:
|
||||
Example: suppose you have a list of comments you want to render. Then, you can render them like this:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/rendering_lists.rs:render_list}}
|
||||
{{#include ../../../examples/rendering_lists.rs:render_list}}
|
||||
```
|
||||
|
||||
### The `key` Attribute
|
||||
|
||||
@@ -9,7 +9,7 @@ Event handlers are similar to regular attributes, but their name usually starts
|
||||
For example, to handle clicks on an element, we can specify an `onclick` handler:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/event_click.rs:rsx}}
|
||||
{{#include ../../../examples/event_click.rs:rsx}}
|
||||
```
|
||||
|
||||
## The `Event` object
|
||||
@@ -30,7 +30,7 @@ To learn what the different event types provide, read the [events module docs](h
|
||||
When you have e.g. a `button` inside a `div`, any click on the `button` is also a click on the `div`. For this reason, Dioxus propagates the click event: first, it is triggered on the target element, then on parent elements. If you want to prevent this behavior, you can call `cancel_bubble()` on the event:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/event_click.rs:rsx}}
|
||||
{{#include ../../../examples/event_click.rs:rsx}}
|
||||
```
|
||||
|
||||
## Prevent Default
|
||||
@@ -40,7 +40,7 @@ Some events have a default behavior. For keyboard events, this might be entering
|
||||
In some instances, might want to avoid this default behavior. For this, you can add the `prevent_default` attribute with the name of the handler whose default behavior you want to stop. This attribute is special: you can attach it multiple times for multiple attributes:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/event_prevent_default.rs:prevent_default}}
|
||||
{{#include ../../../examples/event_prevent_default.rs:prevent_default}}
|
||||
```
|
||||
|
||||
Any event handlers will still be called.
|
||||
@@ -52,15 +52,15 @@ Any event handlers will still be called.
|
||||
Sometimes, you might want to make a component that accepts an event handler. A simple example would be a `FancyButton` component, which accepts an `on_click` handler:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/event_handler_prop.rs:component_with_handler}}
|
||||
{{#include ../../../examples/event_handler_prop.rs:component_with_handler}}
|
||||
```
|
||||
|
||||
Then, you can use it like any other handler:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/event_handler_prop.rs:usage}}
|
||||
{{#include ../../../examples/event_handler_prop.rs:usage}}
|
||||
```
|
||||
|
||||
> Note: just like any other attribute, you can name the handlers anything you want! Though they must start with `on`, for the prop to be automatically turned into an `EventHandler` at the call site.
|
||||
>
|
||||
>
|
||||
> You can also put custom data in the event, rather than e.g. `MouseData`
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
So far our components, being Rust functions, had no state – they were always rendering the same thing. However, in a UI component, it is often useful to have stateful functionality to build user interactions. For example, you might want to track whether the user has openend a drop-down, and render different things accordingly.
|
||||
|
||||
For stateful logic, you can use hooks. Hooks are Rust functions that take a reference to `ScopeState` (in a component, you can pass `&cx`), and provide you with functionality and state.
|
||||
For stateful logic, you can use hooks. Hooks are Rust functions that take a reference to `ScopeState` (in a component, you can pass `&cx`), and provide you with functionality and state.
|
||||
|
||||
## `use_state` Hook
|
||||
|
||||
@@ -15,7 +15,7 @@ For stateful logic, you can use hooks. Hooks are Rust functions that take a refe
|
||||
For example, you might have seen the counter example, in which state (a number) is tracked using the `use_state` hook:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/hooks_counter.rs:component}}
|
||||
{{#include ../../../examples/hooks_counter.rs:component}}
|
||||
```
|
||||

|
||||
|
||||
@@ -26,7 +26,7 @@ Every time the component's state changes, it re-renders, and the component funct
|
||||
You can use multiple hooks in the same component if you want:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/hooks_counter_two_state.rs:component}}
|
||||
{{#include ../../../examples/hooks_counter_two_state.rs:component}}
|
||||
```
|
||||

|
||||
|
||||
@@ -37,7 +37,7 @@ The above example might seem a bit magic, since Rust functions are typically not
|
||||
But how can Dioxus differentiate between multiple hooks in the same component? As you saw in the second example, both `use_state` functions were called with the same parameters, so how come they can return different things when the counters are different?
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/hooks_counter_two_state.rs:use_state_calls}}
|
||||
{{#include ../../../examples/hooks_counter_two_state.rs:use_state_calls}}
|
||||
```
|
||||
|
||||
This is only possible because the two hooks are always called in the same order, so Dioxus knows which is which. So the order you call hooks matters, which is why you must follow certain rules when using hooks:
|
||||
@@ -52,17 +52,17 @@ These rules mean that there are certain things you can't do with hooks:
|
||||
|
||||
### No Hooks in Conditionals
|
||||
```rust
|
||||
{{#include ../../examples/hooks_bad.rs:conditional}}
|
||||
{{#include ../../../examples/hooks_bad.rs:conditional}}
|
||||
```
|
||||
|
||||
### No Hooks in Closures
|
||||
```rust
|
||||
{{#include ../../examples/hooks_bad.rs:closure}}
|
||||
{{#include ../../../examples/hooks_bad.rs:closure}}
|
||||
```
|
||||
|
||||
### No Hooks in Loops
|
||||
```rust
|
||||
{{#include ../../examples/hooks_bad.rs:loop}}
|
||||
{{#include ../../../examples/hooks_bad.rs:loop}}
|
||||
```
|
||||
|
||||
## `use_ref` Hook
|
||||
@@ -76,7 +76,7 @@ Thankfully, there is another hook for that, `use_ref`! It is similar to `use_sta
|
||||
Here's a simple example that keeps a list of events in a `use_ref`. We can acquire write access to the state with `.write()`, and then just `.push` a new value to the state:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/hooks_use_ref.rs:component}}
|
||||
{{#include ../../../examples/hooks_use_ref.rs:component}}
|
||||
```
|
||||
|
||||
> The return values of `use_state` and `use_ref`, (`UseState` and `UseRef`, respectively) are in some ways similar to [`Cell`](https://doc.rust-lang.org/std/cell/) and [`RefCell`](https://doc.rust-lang.org/std/cell/struct.RefCell.html) – they provide interior mutability. However, these Dioxus wrappers also ensure that the component gets re-rendered whenever you change the state.
|
||||
|
||||
@@ -12,7 +12,7 @@ For example, suppose we want to build a meme editor. We want to have an input to
|
||||
|
||||
We start with a `Meme` component, responsible for rendering a meme with a given caption:
|
||||
```rust
|
||||
{{#include ../../examples/meme_editor.rs:meme_component}}
|
||||
{{#include ../../../examples/meme_editor.rs:meme_component}}
|
||||
```
|
||||
|
||||
> Note that the `Meme` component is unaware where the caption is coming from – it could be stored in `use_state`, `use_ref`, or a constant. This ensures that it is very reusable – the same component can be used for a meme gallery without any changes!
|
||||
@@ -20,12 +20,12 @@ We start with a `Meme` component, responsible for rendering a meme with a given
|
||||
We also create a caption editor, completely decoupled from the meme. The caption editor must not store the caption itself – otherwise, how will we provide it to the `Meme` component? Instead, it should accept the current caption as a prop, as well as an event handler to delegate input events to:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/meme_editor.rs:caption_editor}}
|
||||
{{#include ../../../examples/meme_editor.rs:caption_editor}}
|
||||
```
|
||||
|
||||
Finally, a third component will render the other two as children. It will be responsible for keeping the state and passing down the relevant props.
|
||||
```rust
|
||||
{{#include ../../examples/meme_editor.rs:meme_editor}}
|
||||
{{#include ../../../examples/meme_editor.rs:meme_editor}}
|
||||
```
|
||||

|
||||
|
||||
@@ -44,23 +44,23 @@ Dioxus offers a better solution than this "prop drilling" – providing context.
|
||||
First, we have to create a struct for our dark mode configuration:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/meme_editor_dark_mode.rs:DarkMode_struct}}
|
||||
{{#include ../../../examples/meme_editor_dark_mode.rs:DarkMode_struct}}
|
||||
```
|
||||
|
||||
Now, in a top-level component (like `App`), we can provide the `DarkMode` context to all children components:
|
||||
Now, in a top-level component (like `App`), we can provide the `DarkMode` context to all children components:
|
||||
```rust
|
||||
{{#include ../../examples/meme_editor_dark_mode.rs:context_provider}}
|
||||
{{#include ../../../examples/meme_editor_dark_mode.rs:context_provider}}
|
||||
```
|
||||
|
||||
As a result, any child component of `App` (direct or not), can access the `DarkMode` context.
|
||||
```rust
|
||||
{{#include ../../examples/meme_editor_dark_mode.rs:use_context}}
|
||||
{{#include ../../../examples/meme_editor_dark_mode.rs:use_context}}
|
||||
```
|
||||
|
||||
> `use_context` returns `Option<UseSharedState<DarkMode>>` here. If the context has been provided, the value is `Some(UseSharedState)`, which you can call `.read` or `.write` on, similarly to `UseRef`. Otherwise, the value is `None`.
|
||||
|
||||
For example, here's how we would implement the dark mode toggle, which both reads the context (to determine what color it should render) and writes to it (to toggle dark mode):
|
||||
```rust
|
||||
{{#include ../../examples/meme_editor_dark_mode.rs:toggle}}
|
||||
{{#include ../../../examples/meme_editor_dark_mode.rs:toggle}}
|
||||
```
|
||||
|
||||
@@ -7,7 +7,7 @@ Interfaces often need to provide a way to input data: e.g. text, numbers, checkb
|
||||
With controlled inputs, you are directly in charge of the state of the input. This gives you a lot of flexibility, and makes it easy to keep things in sync. For example, this is how you would create a controlled text input:
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/input_controlled.rs:component}}
|
||||
{{#include ../../../examples/input_controlled.rs:component}}
|
||||
```
|
||||
|
||||
Notice the flexibility – you can:
|
||||
@@ -24,7 +24,7 @@ As an alternative to controlled inputs, you can simply let the platform keep tra
|
||||
Since you don't necessarily have the current value of the uncontrolled input in state, you can access it either by listening to `oninput` events (similarly to controlled components), or, if the input is part of a form, you can access the form data in the form events (e.g. `oninput` or `onsubmit`):
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/input_uncontrolled.rs:component}}
|
||||
{{#include ../../../examples/input_uncontrolled.rs:component}}
|
||||
```
|
||||
```
|
||||
Submitted! UiEvent { data: FormData { value: "", values: {"age": "very old", "date": "1966", "name": "Fred"} } }
|
||||
|
||||
Reference in new issue
Block a user