Improve inline docs (#2460)
Improve inline docs * improve incorrect event handler return error message * Improve event handler docs * document the eval functions * document spawn and common spawn errors * fix event handler docs * add notes about how you use attributes and elements in rsx * add doc aliases for attributes and events we rename * add some more aliases for common search terms * don't doc ignore any public examples in core * don't ignore public doc examples in ssr * don't ignore examples in the dioxus package readme * add a warning when you launch without a renderer enabled * fix some outdated element docs * add a bunch of examples to resource * add notes about desktop events * add more docs for use_resource * add on_unimplemented hint to Dependency * fix some unresolved links * add examples to each of the router traits * add not implemented errors for router traits * add an example to the routable trait * expand rsx macro docs * improve memo docs * update the dioxus readme * mention dioxus crate features in the docs * fix a bunch of doc tests * fix html doc tests * fix router doc tests * fix dioxus signals doc tests * fix dioxus ssr doc tests * fix use_future example in the hooks cheat sheet * add a javascript alias for eval * fix hook explanation values * remove unused embed-doc-image dependency
This commit is contained in:
1 parent
054351139f
commit
0127501dbf
71 files changed
+4132
-1162
No files matched your search
@@ -63,6 +63,7 @@ criterion = "0.3.5"
|
||||
thiserror = { workspace = true }
|
||||
env_logger = "0.10.0"
|
||||
tokio = { workspace = true, features = ["full"] }
|
||||
dioxus = { workspace = true }
|
||||
|
||||
[[bench]]
|
||||
name = "jsframework"
|
||||
|
||||
+41
-94
@@ -34,7 +34,7 @@ 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 start with a capital letter and 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`.
|
||||
|
||||
@@ -46,7 +46,7 @@ fn main() {
|
||||
}
|
||||
|
||||
// The #[component] attribute streamlines component creation.
|
||||
// It's not required, but highly recommended. For example, UpperCamelCase components will not generate a warning.
|
||||
// It's not required, but highly recommended. It will lint incorrect component definitions and help you create props structs.
|
||||
#[component]
|
||||
fn App() -> Element {
|
||||
rsx! { "hello world!" }
|
||||
@@ -55,52 +55,42 @@ fn App() -> Element {
|
||||
|
||||
## Elements & your first component
|
||||
|
||||
To assemble UI trees with Dioxus, you need to use the `render` function on
|
||||
something called `LazyNodes`. To produce `LazyNodes`, you can use the `rsx!`
|
||||
macro or the NodeFactory API. For the most part, you want to use the `rsx!`
|
||||
macro.
|
||||
|
||||
You can use the `rsx!` macro to create elements with a jsx-like syntax.
|
||||
Any element in `rsx!` can have attributes, listeners, and children. For
|
||||
consistency, we force all attributes and listeners to be listed _before_
|
||||
children.
|
||||
|
||||
```rust, ignore
|
||||
```rust, no_run
|
||||
# use dioxus::prelude::*;
|
||||
let value = "123";
|
||||
|
||||
rsx! {
|
||||
div {
|
||||
class: "my-class {value}", // <--- attribute
|
||||
onclick: move |_| info!("clicked!"), // <--- listener
|
||||
onclick: move |_| println!("clicked!"), // <--- listener
|
||||
h1 { "hello world" }, // <--- 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.
|
||||
The `rsx!` macro accepts attributes in "struct form". Any rust expression contained within curly braces that implements [`IntoDynNode`](dioxus_core::IntoDynNode) 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 rsx nodes.
|
||||
|
||||
```rust, ignore
|
||||
```rust, no_run
|
||||
# use dioxus::prelude::*;
|
||||
rsx! {
|
||||
div {
|
||||
for _ in 0..10 {
|
||||
span { "hello world" }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `rsx!` macro is what generates the `Element` that our components return.
|
||||
|
||||
```rust, ignore
|
||||
#[component]
|
||||
fn Example() -> Element {
|
||||
rsx!{ "hello world" }
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
Putting everything together, we can write a simple component that renders a list of
|
||||
elements:
|
||||
|
||||
```rust, ignore
|
||||
```rust, no_run
|
||||
# use dioxus::prelude::*;
|
||||
#[component]
|
||||
fn App() -> Element {
|
||||
let name = "dave";
|
||||
@@ -118,12 +108,13 @@ fn App() -> Element {
|
||||
## Components
|
||||
|
||||
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 omit the type altogether.
|
||||
component we design must take some Properties. For components with no explicit properties, we can omit the type altogether.
|
||||
|
||||
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.
|
||||
In Dioxus, all properties are memorized by default with Clone and PartialEq. For props you can't clone, simply wrap the fields in a [`ReadOnlySignal`](dioxus_signals::ReadOnlySignal) and Dioxus will handle converting types for you.
|
||||
|
||||
```rust, ignore
|
||||
```rust, no_run
|
||||
# use dioxus::prelude::*;
|
||||
# #[component] fn Header(title: String, color: String) -> Element { todo!() }
|
||||
#[component]
|
||||
fn App() -> Element {
|
||||
rsx! {
|
||||
@@ -135,64 +126,38 @@ fn App() -> Element {
|
||||
}
|
||||
```
|
||||
|
||||
Our `Header` component takes a `title` and a `color` property, which we
|
||||
declare on an explicit `HeaderProps` struct.
|
||||
The `#[component]` macro will help us automatically create a props struct for our component:
|
||||
|
||||
```rust, ignore
|
||||
// The `Props` derive macro lets us add additional functionality to how props are interpreted.
|
||||
#[derive(Props, PartialEq)]
|
||||
struct HeaderProps {
|
||||
title: String,
|
||||
color: String,
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn Header(props: HeaderProps) -> Element {
|
||||
rsx! {
|
||||
div {
|
||||
background_color: "{props.color}"
|
||||
h1 { "{props.title}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `#[component]` macro also allows you to derive the props
|
||||
struct from function arguments:
|
||||
|
||||
```rust, ignore
|
||||
```rust, no_run
|
||||
# use dioxus::prelude::*;
|
||||
// The component macro turns the arguments for our function into named fields we can pass in to the component in rsx
|
||||
#[component]
|
||||
fn Header(title: String, color: String) -> Element {
|
||||
rsx! {
|
||||
div {
|
||||
background_color: "{color}"
|
||||
background_color: "{color}",
|
||||
h1 { "{title}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Components that begin with an uppercase letter may be called with
|
||||
the traditional (for React) curly-brace syntax like so:
|
||||
|
||||
```rust, ignore
|
||||
rsx! {
|
||||
Header { title: "My App" }
|
||||
}
|
||||
```
|
||||
> You can read more about props in the [reference](https://dioxuslabs.com/learn/0.5/reference/component_props).
|
||||
|
||||
## Hooks
|
||||
|
||||
While components are reusable forms of UI elements, hooks are reusable forms
|
||||
of logic. Hooks provide us a way of retrieving state from Dioxus' internal `Scope` and using
|
||||
of logic. Hooks provide a way of retrieving state from Dioxus' internal `Scope` and using
|
||||
it to render UI elements.
|
||||
|
||||
By convention, all hooks are functions that should start with `use_`. We can
|
||||
use hooks to define the state and modify it from within listeners.
|
||||
|
||||
```rust, ignore
|
||||
```rust, no_run
|
||||
# use dioxus::prelude::*;
|
||||
#[component]
|
||||
fn App() -> Element {
|
||||
// The use signal hook runs once when the component is created and then returns the current value every run after the first
|
||||
let name = use_signal(|| "world");
|
||||
|
||||
rsx! { "hello {name}!" }
|
||||
@@ -202,38 +167,20 @@ fn App() -> Element {
|
||||
Hooks are sensitive to how they are used. To use hooks, you must abide by the
|
||||
["rules of hooks"](https://dioxuslabs.com/learn/0.5/reference/hooks#rules-of-hooks):
|
||||
|
||||
- Functions with "use\_" should not be called in callbacks
|
||||
- Functions with "use\_" should not be called out of order
|
||||
- Functions with "use\_" should not be called in loops or conditionals
|
||||
- Hooks can only be called in the body of a component or another hook. Not inside of another expression like a loop, conditional or function call.
|
||||
- Hooks should start with "use\_"
|
||||
|
||||
In a sense, hooks let us add a field of state to our component without declaring
|
||||
an explicit state struct. However, this means we need to "load" the struct in the right
|
||||
order. If that order is wrong, then the hook will pick the wrong state and panic.
|
||||
|
||||
Most hooks you'll write are simply compositions of other hooks:
|
||||
|
||||
```rust, ignore
|
||||
fn use_username(d: Uuid) -> bool {
|
||||
let users = use_context::<Users>();
|
||||
users.get(&id).map(|user| user.logged_in).ok_or(false)
|
||||
}
|
||||
```
|
||||
|
||||
To create entirely new foundational hooks, we can use the `use_hook` method.
|
||||
|
||||
```rust, ignore
|
||||
fn use_mut_string() -> String {
|
||||
use_hook(|_| "Hello".to_string())
|
||||
}
|
||||
```
|
||||
|
||||
If you want to extend Dioxus with some new functionality, you'll probably want to implement a new hook from scratch.
|
||||
Dioxus includes many built-in hooks that you can use in your components. If those hooks don't fit your use case, you can also extend Dioxus with [custom hooks](https://dioxuslabs.com/learn/0.5/cookbook/state/custom_hooks).
|
||||
|
||||
## Putting it all together
|
||||
|
||||
Using components, templates, and hooks, we can build a simple app.
|
||||
Using components, rsx, and hooks, we can build a simple app.
|
||||
|
||||
```rust, ignore
|
||||
```rust, no_run
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
@@ -244,28 +191,28 @@ fn main() {
|
||||
fn App() -> Element {
|
||||
let mut count = use_signal(|| 0);
|
||||
|
||||
rsx!(
|
||||
rsx! {
|
||||
div { "Count: {count}" }
|
||||
button { onclick: move |_| count += 1, "Increment" }
|
||||
button { onclick: move |_| count -= 1, "Decrement" }
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Features
|
||||
## Conclusion
|
||||
|
||||
This overview doesn't cover everything. Make sure to check out the tutorial and reference guide on the official
|
||||
This overview doesn't cover everything. Make sure to check out the [tutorial](https://dioxuslabs.com/learn/0.5/guide) and [reference](https://dioxuslabs.com/learn/0.5/reference) on the official
|
||||
website for more details.
|
||||
|
||||
Beyond this overview, Dioxus supports:
|
||||
|
||||
- Server-side rendering
|
||||
- [Server-side rendering](https://dioxuslabs.com/learn/0.5/reference/fullstack)
|
||||
- Concurrent rendering (with async support)
|
||||
- Web/Desktop/Mobile support
|
||||
- Pre-rendering and rehydration
|
||||
- Fragments, Portals, and Suspense
|
||||
- Pre-rendering and hydration
|
||||
- Fragments, and Suspense
|
||||
- Inline-styles
|
||||
- Custom event handlers
|
||||
- [Custom event handlers](https://dioxuslabs.com/learn/0.5/reference/event_handlers#handler-props)
|
||||
- Custom elements
|
||||
- Basic fine-grained reactivity (IE SolidJS/Svelte)
|
||||
- and more!
|
||||
|
||||
@@ -37,6 +37,22 @@ type UnsendContext = dyn Fn() -> Box<dyn Any> + 'static;
|
||||
|
||||
impl LaunchBuilder {
|
||||
/// Create a new builder for your application. This will create a launch configuration for the current platform based on the features enabled on the `dioxus` crate.
|
||||
// If you aren't using a third party renderer and this is not a docs.rs build, generate a warning about no renderer being enabled
|
||||
#[cfg_attr(
|
||||
all(not(any(
|
||||
docsrs,
|
||||
feature = "third-party-renderer",
|
||||
feature = "liveview",
|
||||
feature = "desktop",
|
||||
feature = "mobile",
|
||||
feature = "web",
|
||||
feature = "fullstack",
|
||||
feature = "static-generation"
|
||||
))),
|
||||
deprecated(
|
||||
note = "No renderer is enabled. You must enable a renderer feature on the dioxus crate before calling the launch function.\nAdd `web`, `desktop`, `mobile`, `fullstack`, or `static-generation` to the `features` of dioxus field in your Cargo.toml.\n# Example\n```toml\n# ...\n[dependencies]\ndioxus = { version = \"0.5.0\", features = [\"web\"] }\n# ...\n```"
|
||||
)
|
||||
)]
|
||||
pub fn new() -> LaunchBuilder<current_platform::Config, ValidContext> {
|
||||
LaunchBuilder {
|
||||
launch_fn: current_platform::launch,
|
||||
@@ -301,7 +317,24 @@ mod current_platform {
|
||||
}
|
||||
|
||||
/// Launch your application without any additional configuration. See [`LaunchBuilder`] for more options.
|
||||
// If you aren't using a third party renderer and this is not a docs.rs build, generate a warning about no renderer being enabled
|
||||
#[cfg_attr(
|
||||
all(not(any(
|
||||
docsrs,
|
||||
feature = "third-party-renderer",
|
||||
feature = "liveview",
|
||||
feature = "desktop",
|
||||
feature = "mobile",
|
||||
feature = "web",
|
||||
feature = "fullstack",
|
||||
feature = "static-generation"
|
||||
))),
|
||||
deprecated(
|
||||
note = "No renderer is enabled. You must enable a renderer feature on the dioxus crate before calling the launch function.\nAdd `web`, `desktop`, `mobile`, `fullstack`, or `static-generation` to the `features` of dioxus field in your Cargo.toml.\n# Example\n```toml\n# ...\n[dependencies]\ndioxus = { version = \"0.5.0\", features = [\"web\"] }\n# ...\n```"
|
||||
)
|
||||
)]
|
||||
pub fn launch(app: fn() -> Element) {
|
||||
#[allow(deprecated)]
|
||||
LaunchBuilder::new().launch(app)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,26 @@
|
||||
#![doc = include_str!("../README.md")]
|
||||
//!
|
||||
//! ## Dioxus Crate Features
|
||||
//!
|
||||
//! This crate has several features that can be enabled to change the active renderer and enable various integrations:
|
||||
//!
|
||||
//! - `signals`: (default) re-exports `dioxus-signals`
|
||||
//! - `macro`: (default) re-exports `dioxus-macro`
|
||||
//! - `html`: (default) exports `dioxus-html` as the default elements to use in rsx
|
||||
//! - `hooks`: (default) re-exports `dioxus-hooks`
|
||||
//! - `hot-reload`: (default) enables hot rsx reloading in all renderers that support it
|
||||
//! - `router`: exports the [router](https://dioxuslabs.com/learn/0.5/router) and enables any router features for the current platform
|
||||
//! - `third-party-renderer`: Just disables warnings about no active platform when no renderers are enabled
|
||||
//!
|
||||
//! Platform features (the current platform determines what platform the [`launch`](dioxus::prelude::launch) function runs):
|
||||
//!
|
||||
//! - `fullstack`: enables the fullstack platform. This must be used in combination with the `web` feature for wasm builds and `axum` feature for server builds
|
||||
//! - `desktop`: enables the desktop platform
|
||||
//! - `mobile`: enables the mobile platform
|
||||
//! - `web`: enables the web platform. If the fullstack platform is enabled, this will set the fullstack platform to client mode
|
||||
//! - `liveview`: enables the liveview platform
|
||||
//! - `static-generation`: enables the static generation platform. This must be used in combination with the `web` feature for wasm builds and `axum` feature for server builds
|
||||
//! - `axum`: enables the axum server with static generation or fullstack and sets the platform to server mode
|
||||
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/79236386")]
|
||||
#![doc(html_favicon_url = "https://avatars.githubusercontent.com/u/79236386")]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
@@ -11,6 +33,7 @@ mod launch;
|
||||
|
||||
#[cfg(feature = "launch")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "launch")))]
|
||||
#[allow(deprecated)]
|
||||
pub use launch::launch;
|
||||
|
||||
#[cfg(feature = "hooks")]
|
||||
|
||||
Reference in new issue
Block a user