Merge branch 'upstream' into optimize-templates-v3
This commit is contained in:
commit
99a4a9d45b
113 files changed
+336
-817
No files matched your search
@@ -13,7 +13,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
environment: docs
|
environment: docs
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
# NOTE: Comment out when https://github.com/rust-lang/mdBook/pull/1306 is merged and released
|
# NOTE: Comment out when https://github.com/rust-lang/mdBook/pull/1306 is merged and released
|
||||||
# - name: Setup mdBook
|
# - name: Setup mdBook
|
||||||
@@ -32,7 +32,7 @@ jobs:
|
|||||||
cd router && mdbook build -d ../nightly/router && cd ..
|
cd router && mdbook build -d ../nightly/router && cd ..
|
||||||
|
|
||||||
- name: Deploy 🚀
|
- name: Deploy 🚀
|
||||||
uses: JamesIves/github-pages-deploy-action@v4.2.3
|
uses: JamesIves/github-pages-deploy-action@v4.4.1
|
||||||
with:
|
with:
|
||||||
branch: gh-pages # The branch the action should deploy to.
|
branch: gh-pages # The branch the action should deploy to.
|
||||||
folder: docs/nightly # The folder the action should deploy.
|
folder: docs/nightly # The folder the action should deploy.
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ jobs:
|
|||||||
name: Test Suite
|
name: Test Suite
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
profile: minimal
|
profile: minimal
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ jobs:
|
|||||||
name: Check
|
name: Check
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
profile: minimal
|
profile: minimal
|
||||||
@@ -51,7 +51,7 @@ jobs:
|
|||||||
name: Test Suite
|
name: Test Suite
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
profile: minimal
|
profile: minimal
|
||||||
@@ -73,7 +73,7 @@ jobs:
|
|||||||
name: Rustfmt
|
name: Rustfmt
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
profile: minimal
|
profile: minimal
|
||||||
@@ -91,7 +91,7 @@ jobs:
|
|||||||
name: Clippy
|
name: Clippy
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
profile: minimal
|
profile: minimal
|
||||||
@@ -115,7 +115,7 @@ jobs:
|
|||||||
# options: --security-opt seccomp=unconfined
|
# options: --security-opt seccomp=unconfined
|
||||||
# steps:
|
# steps:
|
||||||
# - name: Checkout repository
|
# - name: Checkout repository
|
||||||
# uses: actions/checkout@v2
|
# uses: actions/checkout@v3
|
||||||
# - name: Generate code coverage
|
# - name: Generate code coverage
|
||||||
# run: |
|
# run: |
|
||||||
# apt-get update &&\
|
# apt-get update &&\
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ jobs:
|
|||||||
- name: disable git eol translation
|
- name: disable git eol translation
|
||||||
run: git config --global core.autocrlf false
|
run: git config --global core.autocrlf false
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
# Run build
|
# Run build
|
||||||
- name: Install Rustup using win.rustup.rs
|
- name: Install Rustup using win.rustup.rs
|
||||||
|
|||||||
+1
-6
@@ -16,11 +16,6 @@ members = [
|
|||||||
"packages/autofmt",
|
"packages/autofmt",
|
||||||
"packages/rsx",
|
"packages/rsx",
|
||||||
"docs/guide",
|
"docs/guide",
|
||||||
# "packages/tui",
|
|
||||||
# "packages/native-core",
|
|
||||||
# "packages/native-core-macro",
|
|
||||||
]
|
|
||||||
exclude = [
|
|
||||||
"packages/tui",
|
"packages/tui",
|
||||||
"packages/native-core",
|
"packages/native-core",
|
||||||
"packages/native-core-macro",
|
"packages/native-core-macro",
|
||||||
@@ -40,7 +35,7 @@ homepage = "https://dioxuslabs.com"
|
|||||||
documentation = "https://dioxuslabs.com"
|
documentation = "https://dioxuslabs.com"
|
||||||
keywords = ["dom", "ui", "gui", "react", "wasm"]
|
keywords = ["dom", "ui", "gui", "react", "wasm"]
|
||||||
rust-version = "1.60.0"
|
rust-version = "1.60.0"
|
||||||
|
publish = false
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
dioxus = { path = "./packages/dioxus" }
|
dioxus = { path = "./packages/dioxus" }
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ Dioxus is a portable, performant, and ergonomic framework for building cross-pla
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let mut count = use_state(&cx, || 0);
|
let mut count = use_state(cx, || 0);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
h1 { "High-Five counter: {count}" }
|
h1 { "High-Five counter: {count}" }
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ struct ClickableProps<'a> {
|
|||||||
// ANCHOR: Clickable
|
// ANCHOR: Clickable
|
||||||
fn Clickable<'a>(cx: Scope<'a, ClickableProps<'a>>) -> Element {
|
fn Clickable<'a>(cx: Scope<'a, ClickableProps<'a>>) -> Element {
|
||||||
match cx.props.children {
|
match cx.props.children {
|
||||||
Some(VNode::Text(_)) => {
|
Ok(VNode { dynamic_nodes, .. }) => {
|
||||||
todo!("render some stuff")
|
todo!("render some stuff")
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn App(cx: Scope) -> Element {
|
pub fn App(cx: Scope) -> Element {
|
||||||
let is_logged_in = use_state(&cx, || false);
|
let is_logged_in = use_state(cx, || false);
|
||||||
|
|
||||||
cx.render(rsx!(LogIn {
|
cx.render(rsx!(LogIn {
|
||||||
is_logged_in: **is_logged_in,
|
is_logged_in: **is_logged_in,
|
||||||
@@ -48,7 +48,7 @@ fn LogIn<'a>(
|
|||||||
fn LogInWarning(cx: Scope, is_logged_in: bool) -> Element {
|
fn LogInWarning(cx: Scope, is_logged_in: bool) -> Element {
|
||||||
// ANCHOR: conditional_none
|
// ANCHOR: conditional_none
|
||||||
if *is_logged_in {
|
if *is_logged_in {
|
||||||
return None;
|
return cx.render(rsx!(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use dioxus::events::MouseData;
|
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@@ -20,7 +19,7 @@ fn App(cx: Scope) -> Element {
|
|||||||
// ANCHOR: component_with_handler
|
// ANCHOR: component_with_handler
|
||||||
#[derive(Props)]
|
#[derive(Props)]
|
||||||
pub struct FancyButtonProps<'a> {
|
pub struct FancyButtonProps<'a> {
|
||||||
on_click: EventHandler<'a, MouseData>,
|
on_click: EventHandler<'a, MouseEvent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn FancyButton<'a>(cx: Scope<'a, FancyButtonProps<'a>>) -> Element<'a> {
|
pub fn FancyButton<'a>(cx: Scope<'a, FancyButtonProps<'a>>) -> Element<'a> {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ fn App(cx: Scope) -> Element {
|
|||||||
button {
|
button {
|
||||||
onclick: move |event| {
|
onclick: move |event| {
|
||||||
// now, outer won't be triggered
|
// now, outer won't be triggered
|
||||||
event.cancel_bubble();
|
event.stop_propogation();
|
||||||
},
|
},
|
||||||
"inner"
|
"inner"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ fn App(cx: Scope) -> Element {
|
|||||||
background_color: "red",
|
background_color: "red",
|
||||||
justify_content: "center",
|
justify_content: "center",
|
||||||
align_items: "center",
|
align_items: "center",
|
||||||
onkeydown: move |k: KeyboardEvent| if let KeyCode::Q = k.data.key_code {
|
onkeydown: move |k: KeyboardEvent| if let KeyCode::Q = k.key_code {
|
||||||
tui_ctx.quit();
|
tui_ctx.quit();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -17,13 +17,13 @@ fn App(cx: Scope) -> Element {
|
|||||||
// But `if` statements only run if the conditional is true!
|
// But `if` statements only run if the conditional is true!
|
||||||
// So we might violate rule 2.
|
// So we might violate rule 2.
|
||||||
if you_are_happy && you_know_it {
|
if you_are_happy && you_know_it {
|
||||||
let something = use_state(&cx, || "hands");
|
let something = use_state(cx, || "hands");
|
||||||
println!("clap your {something}")
|
println!("clap your {something}")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ instead, *always* call use_state
|
// ✅ instead, *always* call use_state
|
||||||
// You can put other stuff in the conditional though
|
// You can put other stuff in the conditional though
|
||||||
let something = use_state(&cx, || "hands");
|
let something = use_state(cx, || "hands");
|
||||||
if you_are_happy && you_know_it {
|
if you_are_happy && you_know_it {
|
||||||
println!("clap your {something}")
|
println!("clap your {something}")
|
||||||
}
|
}
|
||||||
@@ -33,12 +33,12 @@ fn App(cx: Scope) -> Element {
|
|||||||
// ❌ don't call hooks inside closures!
|
// ❌ don't call hooks inside closures!
|
||||||
// We can't guarantee that the closure, if used, will be called at the same time every time
|
// We can't guarantee that the closure, if used, will be called at the same time every time
|
||||||
let _a = || {
|
let _a = || {
|
||||||
let b = use_state(&cx, || 0);
|
let b = use_state(cx, || 0);
|
||||||
b.get()
|
b.get()
|
||||||
};
|
};
|
||||||
|
|
||||||
// ✅ instead, move hook `b` outside
|
// ✅ instead, move hook `b` outside
|
||||||
let b = use_state(&cx, || 0);
|
let b = use_state(cx, || 0);
|
||||||
let _a = || b.get();
|
let _a = || b.get();
|
||||||
// ANCHOR_END: closure
|
// ANCHOR_END: closure
|
||||||
|
|
||||||
@@ -50,12 +50,12 @@ fn App(cx: Scope) -> Element {
|
|||||||
// ❌ Do not use hooks in loops!
|
// ❌ Do not use hooks in loops!
|
||||||
// In this case, if the length of the Vec changes, we break rule 2
|
// In this case, if the length of the Vec changes, we break rule 2
|
||||||
for _name in &names {
|
for _name in &names {
|
||||||
let is_selected = use_state(&cx, || false);
|
let is_selected = use_state(cx, || false);
|
||||||
println!("selected: {is_selected}");
|
println!("selected: {is_selected}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ Instead, use a hashmap with use_ref
|
// ✅ Instead, use a hashmap with use_ref
|
||||||
let selection_map = use_ref(&cx, HashMap::<&str, bool>::new);
|
let selection_map = use_ref(cx, HashMap::<&str, bool>::new);
|
||||||
|
|
||||||
for name in &names {
|
for name in &names {
|
||||||
let is_selected = selection_map.read()[name];
|
let is_selected = selection_map.read()[name];
|
||||||
@@ -63,5 +63,5 @@ fn App(cx: Scope) -> Element {
|
|||||||
}
|
}
|
||||||
// ANCHOR_END: loop
|
// ANCHOR_END: loop
|
||||||
|
|
||||||
None
|
cx.render(rsx!(()))
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,6 @@ struct AppSettings {}
|
|||||||
|
|
||||||
// ANCHOR: wrap_context
|
// ANCHOR: wrap_context
|
||||||
fn use_settings(cx: &ScopeState) -> UseSharedState<AppSettings> {
|
fn use_settings(cx: &ScopeState) -> UseSharedState<AppSettings> {
|
||||||
use_context::<AppSettings>(cx).expect("App settings not provided")
|
use_shared_state::<AppSettings>(cx).expect("App settings not provided")
|
||||||
}
|
}
|
||||||
// ANCHOR_END: wrap_context
|
// ANCHOR_END: wrap_context
|
||||||
@@ -7,7 +7,7 @@ fn main() {
|
|||||||
|
|
||||||
// ANCHOR: component
|
// ANCHOR: component
|
||||||
fn App(cx: Scope) -> Element {
|
fn App(cx: Scope) -> Element {
|
||||||
let mut count = use_state(&cx, || 0);
|
let mut count = use_state(cx, || 0);
|
||||||
|
|
||||||
cx.render(rsx!(
|
cx.render(rsx!(
|
||||||
h1 { "High-Five counter: {count}" }
|
h1 { "High-Five counter: {count}" }
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ fn main() {
|
|||||||
// ANCHOR: component
|
// ANCHOR: component
|
||||||
fn App(cx: Scope) -> Element {
|
fn App(cx: Scope) -> Element {
|
||||||
// ANCHOR: use_state_calls
|
// ANCHOR: use_state_calls
|
||||||
let mut count_a = use_state(&cx, || 0);
|
let mut count_a = use_state(cx, || 0);
|
||||||
let mut count_b = use_state(&cx, || 0);
|
let mut count_b = use_state(cx, || 0);
|
||||||
// ANCHOR_END: use_state_calls
|
// ANCHOR_END: use_state_calls
|
||||||
|
|
||||||
cx.render(rsx!(
|
cx.render(rsx!(
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ fn main() {
|
|||||||
|
|
||||||
// ANCHOR: component
|
// ANCHOR: component
|
||||||
fn App(cx: Scope) -> Element {
|
fn App(cx: Scope) -> Element {
|
||||||
let list = use_ref(&cx, Vec::new);
|
let list = use_ref(cx, Vec::new);
|
||||||
let list_formatted = format!("{:?}", *list.read());
|
let list_formatted = format!("{:?}", *list.read());
|
||||||
|
|
||||||
cx.render(rsx!(
|
cx.render(rsx!(
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ fn main() {
|
|||||||
|
|
||||||
// ANCHOR: component
|
// ANCHOR: component
|
||||||
fn App(cx: Scope) -> Element {
|
fn App(cx: Scope) -> Element {
|
||||||
let name = use_state(&cx, || "bob".to_string());
|
let name = use_state(cx, || "bob".to_string());
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
input {
|
input {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// ANCHOR: all
|
// ANCHOR: all
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use dioxus::events::FormData;
|
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@@ -18,7 +17,7 @@ fn MemeEditor(cx: Scope) -> Element {
|
|||||||
width: fit-content;
|
width: fit-content;
|
||||||
";
|
";
|
||||||
|
|
||||||
let caption = use_state(&cx, || "me waiting for my rust code to compile".to_string());
|
let caption = use_state(cx, || "me waiting for my rust code to compile".to_string());
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div {
|
||||||
@@ -83,7 +82,7 @@ fn Meme<'a>(cx: Scope<'a>, caption: &'a str) -> Element<'a> {
|
|||||||
fn CaptionEditor<'a>(
|
fn CaptionEditor<'a>(
|
||||||
cx: Scope<'a>,
|
cx: Scope<'a>,
|
||||||
caption: &'a str,
|
caption: &'a str,
|
||||||
on_input: EventHandler<'a, FormData>,
|
on_input: EventHandler<'a, FormEvent>,
|
||||||
) -> Element<'a> {
|
) -> Element<'a> {
|
||||||
let input_style = r"
|
let input_style = r"
|
||||||
border: none;
|
border: none;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// ANCHOR: all
|
// ANCHOR: all
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use dioxus::events::FormData;
|
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@@ -14,10 +13,10 @@ struct DarkMode(bool);
|
|||||||
|
|
||||||
pub fn App(cx: Scope) -> Element {
|
pub fn App(cx: Scope) -> Element {
|
||||||
// ANCHOR: context_provider
|
// ANCHOR: context_provider
|
||||||
use_context_provider(&cx, || DarkMode(false));
|
use_shared_state_provider(cx, || DarkMode(false));
|
||||||
// ANCHOR_END: context_provider
|
// ANCHOR_END: context_provider
|
||||||
|
|
||||||
let is_dark_mode = use_is_dark_mode(&cx);
|
let is_dark_mode = use_is_dark_mode(cx);
|
||||||
|
|
||||||
let wrapper_style = if is_dark_mode {
|
let wrapper_style = if is_dark_mode {
|
||||||
r"
|
r"
|
||||||
@@ -37,7 +36,7 @@ pub fn App(cx: Scope) -> Element {
|
|||||||
|
|
||||||
pub fn use_is_dark_mode(cx: &ScopeState) -> bool {
|
pub fn use_is_dark_mode(cx: &ScopeState) -> bool {
|
||||||
// ANCHOR: use_context
|
// ANCHOR: use_context
|
||||||
let dark_mode_context = use_context::<DarkMode>(cx);
|
let dark_mode_context = use_shared_state::<DarkMode>(cx);
|
||||||
// ANCHOR_END: use_context
|
// ANCHOR_END: use_context
|
||||||
|
|
||||||
dark_mode_context
|
dark_mode_context
|
||||||
@@ -47,7 +46,7 @@ pub fn use_is_dark_mode(cx: &ScopeState) -> bool {
|
|||||||
|
|
||||||
// ANCHOR: toggle
|
// ANCHOR: toggle
|
||||||
pub fn DarkModeToggle(cx: Scope) -> Element {
|
pub fn DarkModeToggle(cx: Scope) -> Element {
|
||||||
let dark_mode = use_context::<DarkMode>(&cx)?;
|
let dark_mode = use_shared_state::<DarkMode>(cx).unwrap();
|
||||||
|
|
||||||
let style = if dark_mode.read().0 {
|
let style = if dark_mode.read().0 {
|
||||||
"color:white"
|
"color:white"
|
||||||
@@ -71,7 +70,7 @@ pub fn DarkModeToggle(cx: Scope) -> Element {
|
|||||||
|
|
||||||
// ANCHOR: meme_editor
|
// ANCHOR: meme_editor
|
||||||
fn MemeEditor(cx: Scope) -> Element {
|
fn MemeEditor(cx: Scope) -> Element {
|
||||||
let is_dark_mode = use_is_dark_mode(&cx);
|
let is_dark_mode = use_is_dark_mode(cx);
|
||||||
let heading_style = if is_dark_mode { "color: white" } else { "" };
|
let heading_style = if is_dark_mode { "color: white" } else { "" };
|
||||||
|
|
||||||
let container_style = r"
|
let container_style = r"
|
||||||
@@ -82,7 +81,7 @@ fn MemeEditor(cx: Scope) -> Element {
|
|||||||
width: fit-content;
|
width: fit-content;
|
||||||
";
|
";
|
||||||
|
|
||||||
let caption = use_state(&cx, || "me waiting for my rust code to compile".to_string());
|
let caption = use_state(cx, || "me waiting for my rust code to compile".to_string());
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div {
|
||||||
@@ -150,9 +149,9 @@ fn Meme<'a>(cx: Scope<'a>, caption: &'a str) -> Element<'a> {
|
|||||||
fn CaptionEditor<'a>(
|
fn CaptionEditor<'a>(
|
||||||
cx: Scope<'a>,
|
cx: Scope<'a>,
|
||||||
caption: &'a str,
|
caption: &'a str,
|
||||||
on_input: EventHandler<'a, FormData>,
|
on_input: EventHandler<'a, FormEvent>,
|
||||||
) -> Element<'a> {
|
) -> Element<'a> {
|
||||||
let is_dark_mode = use_is_dark_mode(&cx);
|
let is_dark_mode = use_is_dark_mode(cx);
|
||||||
|
|
||||||
let colors = if is_dark_mode {
|
let colors = if is_dark_mode {
|
||||||
r"
|
r"
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ struct Comment {
|
|||||||
|
|
||||||
pub fn App(cx: Scope) -> Element {
|
pub fn App(cx: Scope) -> Element {
|
||||||
// ANCHOR: render_list
|
// ANCHOR: render_list
|
||||||
let comment_field = use_state(&cx, String::new);
|
let comment_field = use_state(cx, String::new);
|
||||||
let mut next_id = use_state(&cx, || 0);
|
let mut next_id = use_state(cx, || 0);
|
||||||
let comments = use_ref(&cx, Vec::<Comment>::new);
|
let comments = use_ref(cx, Vec::<Comment>::new);
|
||||||
|
|
||||||
let comments_lock = comments.read();
|
let comments_lock = comments.read();
|
||||||
let comments_rendered = comments_lock.iter().map(|comment| {
|
let comments_rendered = comments_lock.iter().map(|comment| {
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ pub fn Expression(cx: Scope) -> Element {
|
|||||||
// ANCHOR: expression
|
// ANCHOR: expression
|
||||||
let text = "Dioxus";
|
let text = "Dioxus";
|
||||||
cx.render(rsx!(span {
|
cx.render(rsx!(span {
|
||||||
[text.to_uppercase()]
|
text.to_uppercase()
|
||||||
}))
|
}))
|
||||||
// ANCHOR_END: expression
|
// ANCHOR_END: expression
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@ fn main() {
|
|||||||
|
|
||||||
fn App(cx: Scope) -> Element {
|
fn App(cx: Scope) -> Element {
|
||||||
// ANCHOR: spawn
|
// ANCHOR: spawn
|
||||||
let logged_in = use_state(&cx, || false);
|
let logged_in = use_state(cx, || false);
|
||||||
|
|
||||||
let log_in = move |_| {
|
let log_in = move |_| {
|
||||||
cx.spawn({
|
cx.spawn({
|
||||||
@@ -58,18 +58,18 @@ pub fn Tokio(cx: Scope) -> Element {
|
|||||||
// ANCHOR_END: tokio
|
// ANCHOR_END: tokio
|
||||||
};
|
};
|
||||||
|
|
||||||
None
|
cx.render(rsx!(()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ToOwnedMacro(cx: Scope) -> Element {
|
pub fn ToOwnedMacro(cx: Scope) -> Element {
|
||||||
let count = use_state(&cx, || 0);
|
let count = use_state(cx, || 0);
|
||||||
let age = use_state(&cx, || 0);
|
let age = use_state(cx, || 0);
|
||||||
let name = use_state(&cx, || 0);
|
let name = use_state(cx, || 0);
|
||||||
let description = use_state(&cx, || 0);
|
let description = use_state(cx, || 0);
|
||||||
|
|
||||||
let _ = || {
|
let _ = || {
|
||||||
// ANCHOR: to_owned_macro
|
// ANCHOR: to_owned_macro
|
||||||
use dioxus::core::to_owned;
|
use dioxus::hooks::to_owned;
|
||||||
|
|
||||||
cx.spawn({
|
cx.spawn({
|
||||||
to_owned![count, age, name, description];
|
to_owned![count, age, name, description];
|
||||||
@@ -80,5 +80,5 @@ pub fn ToOwnedMacro(cx: Scope) -> Element {
|
|||||||
// ANCHOR_END: to_owned_macro
|
// ANCHOR_END: to_owned_macro
|
||||||
};
|
};
|
||||||
|
|
||||||
None
|
cx.render(rsx!(()))
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,7 @@ struct ApiResponse {
|
|||||||
|
|
||||||
fn App(cx: Scope) -> Element {
|
fn App(cx: Scope) -> Element {
|
||||||
// ANCHOR: use_future
|
// ANCHOR: use_future
|
||||||
let future = use_future(&cx, (), |_| async move {
|
let future = use_future(cx, (), |_| async move {
|
||||||
reqwest::get("https://dog.ceo/api/breeds/image/random")
|
reqwest::get("https://dog.ceo/api/breeds/image/random")
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -47,7 +47,7 @@ fn App(cx: Scope) -> Element {
|
|||||||
#[inline_props]
|
#[inline_props]
|
||||||
fn RandomDog(cx: Scope, breed: String) -> Element {
|
fn RandomDog(cx: Scope, breed: String) -> Element {
|
||||||
// ANCHOR: dependency
|
// ANCHOR: dependency
|
||||||
let future = use_future(&cx, (breed,), |(breed,)| async move {
|
let future = use_future(cx, (breed,), |(breed,)| async move {
|
||||||
reqwest::get(format!("https://dog.ceo/api/breed/{breed}/images/random"))
|
reqwest::get(format!("https://dog.ceo/api/breed/{breed}/images/random"))
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -56,5 +56,5 @@ fn RandomDog(cx: Scope, breed: String) -> Element {
|
|||||||
});
|
});
|
||||||
// ANCHOR_END: dependency
|
// ANCHOR_END: dependency
|
||||||
|
|
||||||
None
|
cx.render(rsx!(()))
|
||||||
}
|
}
|
||||||
@@ -12,7 +12,7 @@ Your component today might look something like this:
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn Comp(cx: Scope) -> DomTree {
|
fn Comp(cx: Scope) -> DomTree {
|
||||||
let (title, set_title) = use_state(&cx, || "Title".to_string());
|
let (title, set_title) = use_state(cx, || "Title".to_string());
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
input {
|
input {
|
||||||
value: title,
|
value: title,
|
||||||
@@ -26,7 +26,7 @@ This component is fairly straightforward – the input updates its own value on
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn Comp(cx: Scope) -> DomTree {
|
fn Comp(cx: Scope) -> DomTree {
|
||||||
let (title, set_title) = use_state(&cx, || "Title".to_string());
|
let (title, set_title) = use_state(cx, || "Title".to_string());
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
div {
|
div {
|
||||||
input {
|
input {
|
||||||
@@ -49,7 +49,7 @@ We can use signals to generate a two-way binding between data and the input box.
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn Comp(cx: Scope) -> DomTree {
|
fn Comp(cx: Scope) -> DomTree {
|
||||||
let mut title = use_signal(&cx, || String::from("Title"));
|
let mut title = use_signal(cx, || String::from("Title"));
|
||||||
cx.render(rsx!(input { value: title }))
|
cx.render(rsx!(input { value: title }))
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -58,8 +58,8 @@ For a slightly more interesting example, this component calculates the sum betwe
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn Calculator(cx: Scope) -> DomTree {
|
fn Calculator(cx: Scope) -> DomTree {
|
||||||
let mut a = use_signal(&cx, || 0);
|
let mut a = use_signal(cx, || 0);
|
||||||
let mut b = use_signal(&cx, || 0);
|
let mut b = use_signal(cx, || 0);
|
||||||
let mut c = a + b;
|
let mut c = a + b;
|
||||||
rsx! {
|
rsx! {
|
||||||
input { value: a }
|
input { value: a }
|
||||||
@@ -72,8 +72,8 @@ fn Calculator(cx: Scope) -> DomTree {
|
|||||||
Do you notice how we can use built-in operations on signals? Under the hood, we actually create a new derived signal that depends on `a` and `b`. Whenever `a` or `b` update, then `c` will update. If we need to create a new derived signal that's more complex than a basic operation (`std::ops`) we can either chain signals together or combine them:
|
Do you notice how we can use built-in operations on signals? Under the hood, we actually create a new derived signal that depends on `a` and `b`. Whenever `a` or `b` update, then `c` will update. If we need to create a new derived signal that's more complex than a basic operation (`std::ops`) we can either chain signals together or combine them:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let mut a = use_signal(&cx, || 0);
|
let mut a = use_signal(cx, || 0);
|
||||||
let mut b = use_signal(&cx, || 0);
|
let mut b = use_signal(cx, || 0);
|
||||||
|
|
||||||
// Chain signals together using the `with` method
|
// Chain signals together using the `with` method
|
||||||
let c = a.with(b).map(|(a, b)| *a + *b);
|
let c = a.with(b).map(|(a, b)| *a + *b);
|
||||||
@@ -84,7 +84,7 @@ let c = a.with(b).map(|(a, b)| *a + *b);
|
|||||||
If we ever need to get the value out of a signal, we can simply `deref` it.
|
If we ever need to get the value out of a signal, we can simply `deref` it.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let mut a = use_signal(&cx, || 0);
|
let mut a = use_signal(cx, || 0);
|
||||||
let c = *a + *b;
|
let c = *a + *b;
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ Sometimes you want a signal to propagate across your app, either through far-awa
|
|||||||
```rust
|
```rust
|
||||||
const TITLE: Atom<String> = || "".to_string();
|
const TITLE: Atom<String> = || "".to_string();
|
||||||
const Provider: Component = |cx|{
|
const Provider: Component = |cx|{
|
||||||
let title = use_signal(&cx, &TITLE);
|
let title = use_signal(cx, &TITLE);
|
||||||
render!(input { value: title })
|
render!(input { value: title })
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
@@ -106,7 +106,7 @@ If we use the `TITLE` atom in another component, we can cause updates to flow be
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
const Receiver: Component = |cx|{
|
const Receiver: Component = |cx|{
|
||||||
let title = use_signal(&cx, &TITLE);
|
let title = use_signal(cx, &TITLE);
|
||||||
log::info!("This will only be called once!");
|
log::info!("This will only be called once!");
|
||||||
rsx!(cx,
|
rsx!(cx,
|
||||||
div {
|
div {
|
||||||
@@ -133,7 +133,7 @@ Dioxus automatically understands how to use your signals when mixed with iterato
|
|||||||
```rust
|
```rust
|
||||||
const DICT: AtomFamily<String, String> = |_| {};
|
const DICT: AtomFamily<String, String> = |_| {};
|
||||||
const List: Component = |cx|{
|
const List: Component = |cx|{
|
||||||
let dict = use_signal(&cx, &DICT);
|
let dict = use_signal(cx, &DICT);
|
||||||
cx.render(rsx!(
|
cx.render(rsx!(
|
||||||
ul {
|
ul {
|
||||||
For { each: dict, map: |k, v| rsx!( li { "{v}" }) }
|
For { each: dict, map: |k, v| rsx!( li { "{v}" }) }
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ If we represented the reactive graph presented above in Dioxus, it would look ve
|
|||||||
// Declare a component that holds our datasources and calculates `g`
|
// Declare a component that holds our datasources and calculates `g`
|
||||||
fn RenderGraph(cx: Scope) -> Element {
|
fn RenderGraph(cx: Scope) -> Element {
|
||||||
let seconds = use_datasource(SECONDS);
|
let seconds = use_datasource(SECONDS);
|
||||||
let constant = use_state(&cx, || 1);
|
let constant = use_state(cx, || 1);
|
||||||
|
|
||||||
cx.render(rsx!(
|
cx.render(rsx!(
|
||||||
RenderG { seconds: seconds }
|
RenderG { seconds: seconds }
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ If we used global state like use_context or fermi, we might be tempted to inject
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn Titlebar(cx: Scope<TitlebarProps>) -> Element {
|
fn Titlebar(cx: Scope<TitlebarProps>) -> Element {
|
||||||
let title = use_read(&cx, TITLE);
|
let title = use_read(cx, TITLE);
|
||||||
let subtitle = use_read(&cx, SUBTITLE);
|
let subtitle = use_read(cx, SUBTITLE);
|
||||||
|
|
||||||
cx.render(rsx!{/* ui */})
|
cx.render(rsx!{/* ui */})
|
||||||
}
|
}
|
||||||
@@ -43,11 +43,11 @@ To enable our titlebar component to be used across apps, we want to lift our ato
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn DocsiteTitlesection(cx: Scope) {
|
fn DocsiteTitlesection(cx: Scope) {
|
||||||
let title = use_read(&cx, TITLE);
|
let title = use_read(cx, TITLE);
|
||||||
let subtitle = use_read(&cx, SUBTITLE);
|
let subtitle = use_read(cx, SUBTITLE);
|
||||||
|
|
||||||
let username = use_read(&cx, USERNAME);
|
let username = use_read(cx, USERNAME);
|
||||||
let points = use_read(&cx, POINTS);
|
let points = use_read(cx, POINTS);
|
||||||
|
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
TitleBar { title: title, subtitle: subtitle }
|
TitleBar { title: title, subtitle: subtitle }
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ struct Todo {
|
|||||||
is_editing: bool,
|
is_editing: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
let todos = use_ref(&cx, || vec![Todo::new()]);
|
let todos = use_ref(cx, || vec![Todo::new()]);
|
||||||
|
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
ul {
|
ul {
|
||||||
@@ -40,7 +40,7 @@ Instead, let's refactor our Todo component to handle its own state:
|
|||||||
```rust
|
```rust
|
||||||
#[inline_props]
|
#[inline_props]
|
||||||
fn Todo<'a>(cx: Scope, todo: &'a Todo) -> Element {
|
fn Todo<'a>(cx: Scope, todo: &'a Todo) -> Element {
|
||||||
let is_hovered = use_state(&cx, || false);
|
let is_hovered = use_state(cx, || false);
|
||||||
|
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
li {
|
li {
|
||||||
@@ -80,15 +80,15 @@ struct State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// in the component
|
// in the component
|
||||||
let state = use_ref(&cx, State::new)
|
let state = use_ref(cx, State::new)
|
||||||
```
|
```
|
||||||
|
|
||||||
The "better" approach for this particular component would be to break the state apart into different values:
|
The "better" approach for this particular component would be to break the state apart into different values:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let count = use_state(&cx, || 0);
|
let count = use_state(cx, || 0);
|
||||||
let color = use_state(&cx, || "red");
|
let color = use_state(cx, || "red");
|
||||||
let names = use_state(&cx, HashMap::new);
|
let names = use_state(cx, HashMap::new);
|
||||||
```
|
```
|
||||||
|
|
||||||
You might recognize that our "names" value is a HashMap – which is not terribly cheap to clone every time we update its value. To solve this issue, we *highly* suggest using a library like [`im`](https://crates.io/crates/im) which will take advantage of structural sharing to make clones and mutations much cheaper.
|
You might recognize that our "names" value is a HashMap – which is not terribly cheap to clone every time we update its value. To solve this issue, we *highly* suggest using a library like [`im`](https://crates.io/crates/im) which will take advantage of structural sharing to make clones and mutations much cheaper.
|
||||||
@@ -96,7 +96,7 @@ You might recognize that our "names" value is a HashMap – which is not terribl
|
|||||||
When combined with the `make_mut` method on `use_state`, you can get really succinct updates to collections:
|
When combined with the `make_mut` method on `use_state`, you can get really succinct updates to collections:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let todos = use_state(&cx, im_rc::HashMap::default);
|
let todos = use_state(cx, im_rc::HashMap::default);
|
||||||
|
|
||||||
todos.make_mut().insert("new todo", Todo {
|
todos.make_mut().insert("new todo", Todo {
|
||||||
contents: "go get groceries",
|
contents: "go get groceries",
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ For example, let's say we have a component that has two children:
|
|||||||
```rust
|
```rust
|
||||||
fn Demo(cx: Scope) -> Element {
|
fn Demo(cx: Scope) -> Element {
|
||||||
// don't worry about these 2, we'll cover them later
|
// don't worry about these 2, we'll cover them later
|
||||||
let name = use_state(&cx, || String::from("bob"));
|
let name = use_state(cx, || String::from("bob"));
|
||||||
let age = use_state(&cx, || 21);
|
let age = use_state(cx, || 21);
|
||||||
|
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
Name { name: name }
|
Name { name: name }
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ Our component is really simple – we just call `use_ref` to get an initial calc
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let state = use_ref(&cx, Calculator::new);
|
let state = use_ref(cx, Calculator::new);
|
||||||
|
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
// the rendering code
|
// the rendering code
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ The basic setup for coroutines is the `use_coroutine` hook. Most coroutines we w
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let ws: &UseCoroutine<()> = use_coroutine(&cx, |rx| async move {
|
let ws: &UseCoroutine<()> = use_coroutine(cx, |rx| async move {
|
||||||
// Connect to some sort of service
|
// Connect to some sort of service
|
||||||
let mut conn = connect_to_ws_server().await;
|
let mut conn = connect_to_ws_server().await;
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ For many services, a simple async loop will handle the majority of use cases.
|
|||||||
However, if we want to temporarily disable the coroutine, we can "pause" it using the `pause` method, and "resume" it using the `resume` method:
|
However, if we want to temporarily disable the coroutine, we can "pause" it using the `pause` method, and "resume" it using the `resume` method:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let sync: &UseCoroutine<()> = use_coroutine(&cx, |rx| async move {
|
let sync: &UseCoroutine<()> = use_coroutine(cx, |rx| async move {
|
||||||
// code for syncing
|
// code for syncing
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ enum ProfileUpdate {
|
|||||||
SetAge(i32)
|
SetAge(i32)
|
||||||
}
|
}
|
||||||
|
|
||||||
let profile = use_coroutine(&cx, |mut rx: UnboundedReciver<ProfileUpdate>| async move {
|
let profile = use_coroutine(cx, |mut rx: UnboundedReciver<ProfileUpdate>| async move {
|
||||||
let mut server = connect_to_server().await;
|
let mut server = connect_to_server().await;
|
||||||
|
|
||||||
while let Ok(msg) = rx.next().await {
|
while let Ok(msg) = rx.next().await {
|
||||||
@@ -86,9 +86,9 @@ cx.render(rsx!{
|
|||||||
For sufficiently complex apps, we could build a bunch of different useful "services" that loop on channels to update the app.
|
For sufficiently complex apps, we could build a bunch of different useful "services" that loop on channels to update the app.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let profile = use_coroutine(&cx, profile_service);
|
let profile = use_coroutine(cx, profile_service);
|
||||||
let editor = use_coroutine(&cx, editor_service);
|
let editor = use_coroutine(cx, editor_service);
|
||||||
let sync = use_coroutine(&cx, sync_service);
|
let sync = use_coroutine(cx, sync_service);
|
||||||
|
|
||||||
async fn profile_service(rx: UnboundedReceiver<ProfileCommand>) {
|
async fn profile_service(rx: UnboundedReceiver<ProfileCommand>) {
|
||||||
// do stuff
|
// do stuff
|
||||||
@@ -109,9 +109,9 @@ We can combine coroutines with Fermi to emulate Redux Toolkit's Thunk system wit
|
|||||||
static USERNAME: Atom<String> = |_| "default".to_string();
|
static USERNAME: Atom<String> = |_| "default".to_string();
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let atoms = use_atom_root(&cx);
|
let atoms = use_atom_root(cx);
|
||||||
|
|
||||||
use_coroutine(&cx, |rx| sync_service(rx, atoms.clone()));
|
use_coroutine(cx, |rx| sync_service(rx, atoms.clone()));
|
||||||
|
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
Banner {}
|
Banner {}
|
||||||
@@ -119,7 +119,7 @@ fn app(cx: Scope) -> Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn Banner(cx: Scope) -> Element {
|
fn Banner(cx: Scope) -> Element {
|
||||||
let username = use_read(&cx, USERNAME);
|
let username = use_read(cx, USERNAME);
|
||||||
|
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
h1 { "Welcome back, {username}" }
|
h1 { "Welcome back, {username}" }
|
||||||
@@ -158,8 +158,8 @@ To yield values from a coroutine, simply bring in a `UseState` handle and set th
|
|||||||
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let sync_status = use_state(&cx, || Status::Launching);
|
let sync_status = use_state(cx, || Status::Launching);
|
||||||
let sync_task = use_coroutine(&cx, |rx: UnboundedReceiver<SyncAction>| {
|
let sync_task = use_coroutine(cx, |rx: UnboundedReceiver<SyncAction>| {
|
||||||
to_owned![sync_status];
|
to_owned![sync_status];
|
||||||
async move {
|
async move {
|
||||||
loop {
|
loop {
|
||||||
@@ -176,7 +176,7 @@ Coroutine handles are automatically injected through the context API. `use_corou
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn Child(cx: Scope) -> Element {
|
fn Child(cx: Scope) -> Element {
|
||||||
let sync_task = use_coroutine_handle::<SyncAction>(&cx);
|
let sync_task = use_coroutine_handle::<SyncAction>(cx);
|
||||||
|
|
||||||
sync_task.send(SyncAction::SetUsername);
|
sync_task.send(SyncAction::SetUsername);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ The next "best" way of handling errors in Dioxus is to match on the error locall
|
|||||||
To do this, we simply have an error state built into our component:
|
To do this, we simply have an error state built into our component:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let err = use_state(&cx, || None);
|
let err = use_state(cx, || None);
|
||||||
```
|
```
|
||||||
|
|
||||||
Whenever we perform an action that generates an error, we'll set that error state. We can then match on the error in a number of ways (early return, return Element, etc).
|
Whenever we perform an action that generates an error, we'll set that error state. We can then match on the error in a number of ways (early return, return Element, etc).
|
||||||
@@ -64,7 +64,7 @@ Whenever we perform an action that generates an error, we'll set that error stat
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn Commandline(cx: Scope) -> Element {
|
fn Commandline(cx: Scope) -> Element {
|
||||||
let error = use_state(&cx, || None);
|
let error = use_state(cx, || None);
|
||||||
|
|
||||||
cx.render(match *error {
|
cx.render(match *error {
|
||||||
Some(error) => rsx!(
|
Some(error) => rsx!(
|
||||||
@@ -85,7 +85,7 @@ If you're dealing with a handful of components with minimal nesting, you can jus
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn Commandline(cx: Scope) -> Element {
|
fn Commandline(cx: Scope) -> Element {
|
||||||
let error = use_state(&cx, || None);
|
let error = use_state(cx, || None);
|
||||||
|
|
||||||
if let Some(error) = **error {
|
if let Some(error) = **error {
|
||||||
return cx.render(rsx!{ "An error occured" });
|
return cx.render(rsx!{ "An error occured" });
|
||||||
@@ -125,7 +125,7 @@ Then, in our top level component, we want to explicitly handle the possible erro
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn TopLevel(cx: Scope) -> Element {
|
fn TopLevel(cx: Scope) -> Element {
|
||||||
let error = use_read(&cx, INPUT_ERROR);
|
let error = use_read(cx, INPUT_ERROR);
|
||||||
|
|
||||||
match error {
|
match error {
|
||||||
TooLong => return cx.render(rsx!{ "FAILED: Too long!" }),
|
TooLong => return cx.render(rsx!{ "FAILED: Too long!" }),
|
||||||
@@ -139,7 +139,7 @@ Now, whenever a downstream component has an error in its actions, it can simply
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn Commandline(cx: Scope) -> Element {
|
fn Commandline(cx: Scope) -> Element {
|
||||||
let set_error = use_set(&cx, INPUT_ERROR);
|
let set_error = use_set(cx, INPUT_ERROR);
|
||||||
|
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
input {
|
input {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ Dioxus is a portable, performant, and ergonomic framework for building cross-pla
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let mut count = use_state(&cx, || 0);
|
let mut count = use_state(cx, || 0);
|
||||||
|
|
||||||
cx.render(rsx!(
|
cx.render(rsx!(
|
||||||
h1 { "High-Five counter: {count}" }
|
h1 { "High-Five counter: {count}" }
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ A configuração básica para corrotinas é o _hook_ `use_coroutine`. A maioria
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let ws: &UseCoroutine<()> = use_coroutine(&cx, |rx| async move {
|
let ws: &UseCoroutine<()> = use_coroutine(cx, |rx| async move {
|
||||||
// Connect to some sort of service
|
// Connect to some sort of service
|
||||||
let mut conn = connect_to_ws_server().await;
|
let mut conn = connect_to_ws_server().await;
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ Para muitos serviços, um _loop_ assíncrono simples lidará com a maioria dos c
|
|||||||
No entanto, se quisermos desabilitar temporariamente a corrotina, podemos "pausá-la" usando o método `pause` e "retomá-la" usando o método `resume`:
|
No entanto, se quisermos desabilitar temporariamente a corrotina, podemos "pausá-la" usando o método `pause` e "retomá-la" usando o método `resume`:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let sync: &UseCoroutine<()> = use_coroutine(&cx, |rx| async move {
|
let sync: &UseCoroutine<()> = use_coroutine(cx, |rx| async move {
|
||||||
// code for syncing
|
// code for syncing
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ enum ProfileUpdate {
|
|||||||
SetAge(i32)
|
SetAge(i32)
|
||||||
}
|
}
|
||||||
|
|
||||||
let profile = use_coroutine(&cx, |mut rx: UnboundedReciver<ProfileUpdate>| async move {
|
let profile = use_coroutine(cx, |mut rx: UnboundedReciver<ProfileUpdate>| async move {
|
||||||
let mut server = connect_to_server().await;
|
let mut server = connect_to_server().await;
|
||||||
|
|
||||||
while let Ok(msg) = rx.next().await {
|
while let Ok(msg) = rx.next().await {
|
||||||
@@ -85,9 +85,9 @@ cx.render(rsx!{
|
|||||||
Para aplicativos suficientemente complexos, poderíamos criar vários "serviços" úteis diferentes que fazem um _loop_ nos canais para atualizar o aplicativo.
|
Para aplicativos suficientemente complexos, poderíamos criar vários "serviços" úteis diferentes que fazem um _loop_ nos canais para atualizar o aplicativo.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let profile = use_coroutine(&cx, profile_service);
|
let profile = use_coroutine(cx, profile_service);
|
||||||
let editor = use_coroutine(&cx, editor_service);
|
let editor = use_coroutine(cx, editor_service);
|
||||||
let sync = use_coroutine(&cx, sync_service);
|
let sync = use_coroutine(cx, sync_service);
|
||||||
|
|
||||||
async fn profile_service(rx: UnboundedReceiver<ProfileCommand>) {
|
async fn profile_service(rx: UnboundedReceiver<ProfileCommand>) {
|
||||||
// do stuff
|
// do stuff
|
||||||
@@ -108,9 +108,9 @@ Podemos combinar corrotinas com `Fermi` para emular o sistema `Thunk` do **Redux
|
|||||||
static USERNAME: Atom<String> = |_| "default".to_string();
|
static USERNAME: Atom<String> = |_| "default".to_string();
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let atoms = use_atom_root(&cx);
|
let atoms = use_atom_root(cx);
|
||||||
|
|
||||||
use_coroutine(&cx, |rx| sync_service(rx, atoms.clone()));
|
use_coroutine(cx, |rx| sync_service(rx, atoms.clone()));
|
||||||
|
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
Banner {}
|
Banner {}
|
||||||
@@ -118,7 +118,7 @@ fn app(cx: Scope) -> Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn Banner(cx: Scope) -> Element {
|
fn Banner(cx: Scope) -> Element {
|
||||||
let username = use_read(&cx, USERNAME);
|
let username = use_read(cx, USERNAME);
|
||||||
|
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
h1 { "Welcome back, {username}" }
|
h1 { "Welcome back, {username}" }
|
||||||
@@ -156,8 +156,8 @@ async fn sync_service(mut rx: UnboundedReceiver<SyncAction>, atoms: AtomRoot) {
|
|||||||
Para obter valores de uma corrotina, basta usar um identificador `UseState` e definir o valor sempre que sua corrotina concluir seu trabalho.
|
Para obter valores de uma corrotina, basta usar um identificador `UseState` e definir o valor sempre que sua corrotina concluir seu trabalho.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let sync_status = use_state(&cx, || Status::Launching);
|
let sync_status = use_state(cx, || Status::Launching);
|
||||||
let sync_task = use_coroutine(&cx, |rx: UnboundedReceiver<SyncAction>| {
|
let sync_task = use_coroutine(cx, |rx: UnboundedReceiver<SyncAction>| {
|
||||||
to_owned![sync_status];
|
to_owned![sync_status];
|
||||||
async move {
|
async move {
|
||||||
loop {
|
loop {
|
||||||
@@ -174,7 +174,7 @@ Os identificadores de corrotina são injetados automaticamente por meio da API d
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn Child(cx: Scope) -> Element {
|
fn Child(cx: Scope) -> Element {
|
||||||
let sync_task = use_coroutine_handle::<SyncAction>(&cx);
|
let sync_task = use_coroutine_handle::<SyncAction>(cx);
|
||||||
|
|
||||||
sync_task.send(SyncAction::SetUsername);
|
sync_task.send(SyncAction::SetUsername);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,14 +53,14 @@ A próxima "melhor" maneira de lidar com erros no Dioxus é combinar (`match`) o
|
|||||||
Para fazer isso, simplesmente temos um estado de erro embutido em nosso componente:
|
Para fazer isso, simplesmente temos um estado de erro embutido em nosso componente:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let err = use_state(&cx, || None);
|
let err = use_state(cx, || None);
|
||||||
```
|
```
|
||||||
|
|
||||||
Sempre que realizarmos uma ação que gere um erro, definiremos esse estado de erro. Podemos então combinar o erro de várias maneiras (retorno antecipado, elemento de retorno etc.).
|
Sempre que realizarmos uma ação que gere um erro, definiremos esse estado de erro. Podemos então combinar o erro de várias maneiras (retorno antecipado, elemento de retorno etc.).
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn Commandline(cx: Scope) -> Element {
|
fn Commandline(cx: Scope) -> Element {
|
||||||
let error = use_state(&cx, || None);
|
let error = use_state(cx, || None);
|
||||||
|
|
||||||
cx.render(match *error {
|
cx.render(match *error {
|
||||||
Some(error) => rsx!(
|
Some(error) => rsx!(
|
||||||
@@ -81,7 +81,7 @@ Se você estiver lidando com alguns componentes com um mínimo de aninhamento, b
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn Commandline(cx: Scope) -> Element {
|
fn Commandline(cx: Scope) -> Element {
|
||||||
let error = use_state(&cx, || None);
|
let error = use_state(cx, || None);
|
||||||
|
|
||||||
if let Some(error) = **error {
|
if let Some(error) = **error {
|
||||||
return cx.render(rsx!{ "An error occured" });
|
return cx.render(rsx!{ "An error occured" });
|
||||||
@@ -120,7 +120,7 @@ Então, em nosso componente de nível superior, queremos tratar explicitamente o
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn TopLevel(cx: Scope) -> Element {
|
fn TopLevel(cx: Scope) -> Element {
|
||||||
let error = use_read(&cx, INPUT_ERROR);
|
let error = use_read(cx, INPUT_ERROR);
|
||||||
|
|
||||||
match error {
|
match error {
|
||||||
TooLong => return cx.render(rsx!{ "FAILED: Too long!" }),
|
TooLong => return cx.render(rsx!{ "FAILED: Too long!" }),
|
||||||
@@ -134,7 +134,7 @@ Agora, sempre que um componente _downstream_ tiver um erro em suas ações, ele
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn Commandline(cx: Scope) -> Element {
|
fn Commandline(cx: Scope) -> Element {
|
||||||
let set_error = use_set(&cx, INPUT_ERROR);
|
let set_error = use_set(cx, INPUT_ERROR);
|
||||||
|
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
input {
|
input {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ Dioxus é uma estrutura portátil, de alto desempenho e ergonômica para a const
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let mut count = use_state(&cx, || 0);
|
let mut count = use_state(cx, || 0);
|
||||||
|
|
||||||
cx.render(rsx!(
|
cx.render(rsx!(
|
||||||
h1 { "High-Five counter: {count}" }
|
h1 { "High-Five counter: {count}" }
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ Dioxus is a recently-released library for building interactive user interfaces (
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let mut count = use_state(&cx, || 0);
|
let mut count = use_state(cx, || 0);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
h1 { "Count: {count}" }
|
h1 { "Count: {count}" }
|
||||||
@@ -102,8 +102,8 @@ We're also using hooks to parse the URL parameters and segments so you can inter
|
|||||||
struct Query { name: String }
|
struct Query { name: String }
|
||||||
|
|
||||||
fn BlogPost(cx: Scope) -> Element {
|
fn BlogPost(cx: Scope) -> Element {
|
||||||
let post = use_route(&cx).segment("post")?;
|
let post = use_route(cx).segment("post")?;
|
||||||
let query = use_route(&cx).query::<Query>()?;
|
let query = use_route(cx).query::<Query>()?;
|
||||||
|
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
"Viewing post {post}"
|
"Viewing post {post}"
|
||||||
@@ -128,7 +128,7 @@ static TITLE: Atom<&str> = |_| "Hello";
|
|||||||
|
|
||||||
// Read the value from anywhere in the app, subscribing to any changes
|
// Read the value from anywhere in the app, subscribing to any changes
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let title = use_read(&cx, TITLE);
|
let title = use_read(cx, TITLE);
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
h1 { "{title}" }
|
h1 { "{title}" }
|
||||||
Child {}
|
Child {}
|
||||||
@@ -137,7 +137,7 @@ fn app(cx: Scope) -> Element {
|
|||||||
|
|
||||||
// Set the value from anywhere in the app
|
// Set the value from anywhere in the app
|
||||||
fn Child(cx: Scope) -> Element {
|
fn Child(cx: Scope) -> Element {
|
||||||
let set_title = use_set(&cx, TITLE);
|
let set_title = use_set(cx, TITLE);
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
button {
|
button {
|
||||||
onclick: move |_| set_title("goodbye"),
|
onclick: move |_| set_title("goodbye"),
|
||||||
@@ -245,7 +245,7 @@ First, we upgraded the `use_future` hook. It now supports dependencies, which le
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn RenderDog(cx: Scope, breed: String) -> Element {
|
fn RenderDog(cx: Scope, breed: String) -> Element {
|
||||||
let dog_request = use_future(&cx, (breed,), |(breed,)| async move {
|
let dog_request = use_future(cx, (breed,), |(breed,)| async move {
|
||||||
reqwest::get(format!("https://dog.ceo/api/breed/{}/images/random", breed))
|
reqwest::get(format!("https://dog.ceo/api/breed/{}/images/random", breed))
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -265,7 +265,7 @@ Additionally, we added better support for coroutines. You can now start, stop, r
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn App(cx: Scope) -> Element {
|
fn App(cx: Scope) -> Element {
|
||||||
let sync_task = use_coroutine(&cx, |rx| async move {
|
let sync_task = use_coroutine(cx, |rx| async move {
|
||||||
connect_to_server().await;
|
connect_to_server().await;
|
||||||
let state = MyState::new();
|
let state = MyState::new();
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let mut count = use_state(&cx, || 0);
|
let mut count = use_state(cx, || 0);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
h1 { "Count: {count}" }
|
h1 { "Count: {count}" }
|
||||||
@@ -138,7 +138,7 @@ struct CardProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Card: Component<CardProps> = |cx| {
|
static Card: Component<CardProps> = |cx| {
|
||||||
let mut count = use_state(&cx, || 0);
|
let mut count = use_state(cx, || 0);
|
||||||
cx.render(rsx!(
|
cx.render(rsx!(
|
||||||
aside {
|
aside {
|
||||||
h2 { "{cx.props.title}" }
|
h2 { "{cx.props.title}" }
|
||||||
@@ -191,7 +191,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let mut count = use_state(&cx, || 0);
|
let mut count = use_state(cx, || 0);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
h1 { "Count: {count}" }
|
h1 { "Count: {count}" }
|
||||||
@@ -260,7 +260,7 @@ Dioxus understands the lifetimes of data borrowed from `Scope`, so you can safel
|
|||||||
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let name = use_state(&cx, || "asd");
|
let name = use_state(cx, || "asd");
|
||||||
rsx! {
|
rsx! {
|
||||||
div {
|
div {
|
||||||
button { onclick: move |_| name.set("abc") }
|
button { onclick: move |_| name.set("abc") }
|
||||||
@@ -274,7 +274,7 @@ Because we know the lifetime of your handlers, we can also expose this to childr
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let name = use_state(&cx, || "asd");
|
let name = use_state(cx, || "asd");
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
Button { name: name }
|
Button { name: name }
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ use dioxus::{
|
|||||||
...
|
...
|
||||||
|
|
||||||
fn blog_post(cx: Scope) -> Element {
|
fn blog_post(cx: Scope) -> Element {
|
||||||
let route = use_route(&cx); // NEW
|
let route = use_route(cx); // NEW
|
||||||
let blog_text = "";
|
let blog_text = "";
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
@@ -165,7 +165,7 @@ Dioxus Router provides built in methods to extract information from a route. We
|
|||||||
The ``segment`` method also parses the parameter into any type for us. We'll use a match expression that handles a parsing error and on success, uses our helper function to grab the blog post.
|
The ``segment`` method also parses the parameter into any type for us. We'll use a match expression that handles a parsing error and on success, uses our helper function to grab the blog post.
|
||||||
```rs
|
```rs
|
||||||
fn blog_post(cx: Scope) -> Element {
|
fn blog_post(cx: Scope) -> Element {
|
||||||
let route = use_route(&cx);
|
let route = use_route(cx);
|
||||||
|
|
||||||
// NEW
|
// NEW
|
||||||
let blog_text = match route.segment::<String>("post").unwrap() {
|
let blog_text = match route.segment::<String>("post").unwrap() {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ const RECT_STYLE: &str = r#"
|
|||||||
"#;
|
"#;
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let events = use_ref(&cx, std::collections::VecDeque::new);
|
let events = use_ref(cx, std::collections::VecDeque::new);
|
||||||
|
|
||||||
let log_event = move |event: Event| {
|
let log_event = move |event: Event| {
|
||||||
let mut events = events.write();
|
let mut events = events.write();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let val = use_state(&cx, || String::from("0"));
|
let val = use_state(cx, || String::from("0"));
|
||||||
|
|
||||||
let input_digit = move |num: u8| {
|
let input_digit = move |num: u8| {
|
||||||
if val.get() == "0" {
|
if val.get() == "0" {
|
||||||
|
|||||||
+4
-4
@@ -16,10 +16,10 @@ pub struct Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let clients = use_ref(&cx, || vec![] as Vec<Client>);
|
let clients = use_ref(cx, || vec![] as Vec<Client>);
|
||||||
let firstname = use_state(&cx, String::new);
|
let firstname = use_state(cx, String::new);
|
||||||
let lastname = use_state(&cx, String::new);
|
let lastname = use_state(cx, String::new);
|
||||||
let description = use_state(&cx, String::new);
|
let description = use_state(cx, String::new);
|
||||||
|
|
||||||
cx.render(rsx!(
|
cx.render(rsx!(
|
||||||
body {
|
body {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
// let nf = NodeFactory::new(&cx);
|
// let nf = NodeFactory::new(cx);
|
||||||
|
|
||||||
// let mut attrs = dioxus::core::exports::bumpalo::collections::Vec::new_in(nf.bump());
|
// let mut attrs = dioxus::core::exports::bumpalo::collections::Vec::new_in(nf.bump());
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let disabled = use_state(&cx, || false);
|
let disabled = use_state(cx, || false);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let val = use_state(&cx, || "0.0001");
|
let val = use_state(cx, || "0.0001");
|
||||||
|
|
||||||
let num = match val.parse::<f32>() {
|
let num = match val.parse::<f32>() {
|
||||||
Err(_) => return cx.render(rsx!("Parsing failed")),
|
Err(_) => return cx.render(rsx!("Parsing failed")),
|
||||||
|
|||||||
+2
-2
@@ -5,8 +5,8 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let script = use_state(&cx, String::new);
|
let script = use_state(cx, String::new);
|
||||||
let eval = dioxus_desktop::use_eval(&cx);
|
let eval = dioxus_desktop::use_eval(cx);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div {
|
||||||
|
|||||||
+3
-3
@@ -10,7 +10,7 @@ fn main() {
|
|||||||
static NAME: Atom<String> = |_| "world".to_string();
|
static NAME: Atom<String> = |_| "world".to_string();
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let name = use_read(&cx, NAME);
|
let name = use_read(cx, NAME);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div { "hello {name}!" }
|
div { "hello {name}!" }
|
||||||
@@ -20,7 +20,7 @@ fn app(cx: Scope) -> Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn Child(cx: Scope) -> Element {
|
fn Child(cx: Scope) -> Element {
|
||||||
let set_name = use_set(&cx, NAME);
|
let set_name = use_set(cx, NAME);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
button {
|
button {
|
||||||
@@ -33,7 +33,7 @@ fn Child(cx: Scope) -> Element {
|
|||||||
static NAMES: AtomRef<Vec<String>> = |_| vec!["world".to_string()];
|
static NAMES: AtomRef<Vec<String>> = |_| vec!["world".to_string()];
|
||||||
|
|
||||||
fn ChildWithRef(cx: Scope) -> Element {
|
fn ChildWithRef(cx: Scope) -> Element {
|
||||||
let names = use_atom_ref(&cx, NAMES);
|
let names = use_atom_ref(cx, NAMES);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let files = use_ref(&cx, Files::new);
|
let files = use_ref(cx, Files::new);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div {
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ impl Label {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let items = use_ref(&cx, Vec::new);
|
let items = use_ref(cx, Vec::new);
|
||||||
let selected = use_state(&cx, || None);
|
let selected = use_state(cx, || None);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div { class: "container",
|
div { class: "container",
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let val = use_state(&cx, || 0);
|
let val = use_state(cx, || 0);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let state = use_state(&cx, || 1);
|
let state = use_state(cx, || 1);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let state = use_ref(&cx, Calculator::new);
|
let state = use_ref(cx, Calculator::new);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
style { include_str!("./assets/calculator.css") }
|
style { include_str!("./assets/calculator.css") }
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let state = use_state(&cx, PlayerState::new);
|
let state = use_state(cx, PlayerState::new);
|
||||||
|
|
||||||
cx.render(rsx!(
|
cx.render(rsx!(
|
||||||
div {
|
div {
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let mut count = use_state(&cx, || 0);
|
let mut count = use_state(cx, || 0);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
h1 { "High-Five counter: {count}" }
|
h1 { "High-Five counter: {count}" }
|
||||||
|
|||||||
+3
-3
@@ -30,7 +30,7 @@ fn app(cx: Scope) -> Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn BlogPost(cx: Scope) -> Element {
|
fn BlogPost(cx: Scope) -> Element {
|
||||||
let post = dioxus_router::use_route(&cx).last_segment().unwrap();
|
let post = dioxus_router::use_route(cx).last_segment().unwrap();
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div {
|
||||||
@@ -46,9 +46,9 @@ struct Query {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn User(cx: Scope) -> Element {
|
fn User(cx: Scope) -> Element {
|
||||||
let post = dioxus_router::use_route(&cx).last_segment().unwrap();
|
let post = dioxus_router::use_route(cx).last_segment().unwrap();
|
||||||
|
|
||||||
let query = dioxus_router::use_route(&cx)
|
let query = dioxus_router::use_route(cx)
|
||||||
.query::<Query>()
|
.query::<Query>()
|
||||||
.unwrap_or(Query { bold: false });
|
.unwrap_or(Query { bold: false });
|
||||||
|
|
||||||
|
|||||||
@@ -13,14 +13,14 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn example(cx: Scope) -> Element {
|
fn example(cx: Scope) -> Element {
|
||||||
let items = use_state(&cx, || {
|
let items = use_state(cx, || {
|
||||||
vec![Thing {
|
vec![Thing {
|
||||||
a: "asd".to_string(),
|
a: "asd".to_string(),
|
||||||
b: 10,
|
b: 10,
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
|
|
||||||
let things = use_ref(&cx, || {
|
let things = use_ref(cx, || {
|
||||||
vec![Thing {
|
vec![Thing {
|
||||||
a: "asd".to_string(),
|
a: "asd".to_string(),
|
||||||
b: 10,
|
b: 10,
|
||||||
@@ -28,7 +28,7 @@ fn example(cx: Scope) -> Element {
|
|||||||
});
|
});
|
||||||
let things_list = things.read();
|
let things_list = things.read();
|
||||||
|
|
||||||
let mything = use_ref(&cx, || Some(String::from("asd")));
|
let mything = use_ref(cx, || Some(String::from("asd")));
|
||||||
let mything_read = mything.read();
|
let mything_read = mything.read();
|
||||||
|
|
||||||
cx.render(rsx!(
|
cx.render(rsx!(
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ fn app(cx: Scope) -> Element {
|
|||||||
|
|
||||||
// helper functions
|
// helper functions
|
||||||
// Anything that implements IntoVnode can be dropped directly into Rsx
|
// Anything that implements IntoVnode can be dropped directly into Rsx
|
||||||
helper(&cx, "hello world!")
|
helper(cx, "hello world!")
|
||||||
|
|
||||||
// Strings can be supplied directly
|
// Strings can be supplied directly
|
||||||
String::from("Hello world!")
|
String::from("Hello world!")
|
||||||
|
|||||||
+5
-13
@@ -2,16 +2,13 @@
|
|||||||
//!
|
//!
|
||||||
//! This example shows how we can render the Dioxus Virtualdom using SSR.
|
//! This example shows how we can render the Dioxus Virtualdom using SSR.
|
||||||
|
|
||||||
use std::fmt::Write;
|
|
||||||
|
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use dioxus_ssr::config::Config;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// We can render VirtualDoms
|
// We can render VirtualDoms
|
||||||
let mut vdom = VirtualDom::new(app);
|
let mut vdom = VirtualDom::new(app);
|
||||||
let _ = vdom.rebuild();
|
let _ = vdom.rebuild();
|
||||||
println!("{}", dioxus_ssr::render_vdom(&vdom));
|
println!("{}", dioxus_ssr::render(&vdom));
|
||||||
|
|
||||||
// Or we can render rsx! calls themselves
|
// Or we can render rsx! calls themselves
|
||||||
println!(
|
println!(
|
||||||
@@ -24,17 +21,12 @@ fn main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// We can configure the SSR rendering to add ids for rehydration
|
// We can configure the SSR rendering to add ids for rehydration
|
||||||
println!(
|
println!("{}", dioxus_ssr::pre_render(&vdom));
|
||||||
"{}",
|
|
||||||
dioxus_ssr::render_vdom_cfg(&vdom, Config::default().pre_render(true))
|
|
||||||
);
|
|
||||||
|
|
||||||
// We can even render as a writer
|
// We can render to a buf directly too
|
||||||
let mut file = String::new();
|
let mut file = String::new();
|
||||||
let _ = file.write_fmt(format_args!(
|
let mut renderer = dioxus_ssr::Renderer::default();
|
||||||
"{}",
|
renderer.render_to(&mut file, &vdom).unwrap();
|
||||||
dioxus_ssr::SsrRender::default().render_vdom(&vdom)
|
|
||||||
));
|
|
||||||
println!("{}", file);
|
println!("{}", file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ fn app(cx: Scope) -> Element {
|
|||||||
/// Suspense is achieved my moving the future into only the component that
|
/// Suspense is achieved my moving the future into only the component that
|
||||||
/// actually renders the data.
|
/// actually renders the data.
|
||||||
fn Doggo(cx: Scope) -> Element {
|
fn Doggo(cx: Scope) -> Element {
|
||||||
let fut = use_future(&cx, (), |_| async move {
|
let fut = use_future(cx, (), |_| async move {
|
||||||
reqwest::get("https://dog.ceo/api/breeds/image/random/")
|
reqwest::get("https://dog.ceo/api/breeds/image/random/")
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let val = use_state(&cx, || 5);
|
let val = use_state(cx, || 5);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div {
|
||||||
|
|||||||
+2
-2
@@ -10,9 +10,9 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let count = use_state(&cx, || 0);
|
let count = use_state(cx, || 0);
|
||||||
|
|
||||||
use_future(&cx, (), move |_| {
|
use_future(cx, (), move |_| {
|
||||||
let mut count = count.clone();
|
let mut count = count.clone();
|
||||||
async move {
|
async move {
|
||||||
loop {
|
loop {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let model = use_state(&cx, || String::from("asd"));
|
let model = use_state(cx, || String::from("asd"));
|
||||||
|
|
||||||
println!("{}", model);
|
println!("{}", model);
|
||||||
|
|
||||||
|
|||||||
@@ -12,15 +12,15 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let window = dioxus_desktop::use_window(&cx);
|
let window = dioxus_desktop::use_window(cx);
|
||||||
|
|
||||||
// if you want to make window fullscreen, you need close the resizable.
|
// if you want to make window fullscreen, you need close the resizable.
|
||||||
// window.set_fullscreen(true);
|
// window.set_fullscreen(true);
|
||||||
// window.set_resizable(false);
|
// window.set_resizable(false);
|
||||||
|
|
||||||
let fullscreen = use_state(&cx, || false);
|
let fullscreen = use_state(cx, || false);
|
||||||
let always_on_top = use_state(&cx, || false);
|
let always_on_top = use_state(cx, || false);
|
||||||
let decorations = use_state(&cx, || false);
|
let decorations = use_state(cx, || false);
|
||||||
|
|
||||||
cx.render(rsx!(
|
cx.render(rsx!(
|
||||||
link { href:"https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css", rel:"stylesheet" }
|
link { href:"https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css", rel:"stylesheet" }
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let window = use_window(&cx);
|
let window = use_window(cx);
|
||||||
|
|
||||||
let level = use_state(&cx, || 1.0);
|
let level = use_state(cx, || 1.0);
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
input {
|
input {
|
||||||
r#type: "number",
|
r#type: "number",
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let contents = use_state(&cx, || {
|
let contents = use_state(cx, || {
|
||||||
String::from("<script>alert(\"hello world\")</script>")
|
String::from("<script>alert(\"hello world\")</script>")
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -233,7 +233,7 @@ use hooks to define state and modify it from within listeners.
|
|||||||
|
|
||||||
```rust, ignore
|
```rust, ignore
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let name = use_state(&cx, || "world");
|
let name = use_state(cx, || "world");
|
||||||
|
|
||||||
render!("hello {name}!")
|
render!("hello {name}!")
|
||||||
}
|
}
|
||||||
@@ -280,7 +280,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn App(cx: Scope) -> Element {
|
fn App(cx: Scope) -> Element {
|
||||||
let count = use_state(&cx, || 0);
|
let count = use_state(cx, || 0);
|
||||||
|
|
||||||
cx.render(rsx!(
|
cx.render(rsx!(
|
||||||
div { "Count: {count}" }
|
div { "Count: {count}" }
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ Dioxus 是一个可移植的、高性能的、符合人体工程学的框架,
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let mut count = use_state(&cx, || 0);
|
let mut count = use_state(cx, || 0);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
h1 { "High-Five counter: {count}" }
|
h1 { "High-Five counter: {count}" }
|
||||||
|
|||||||
@@ -406,8 +406,8 @@ enum Patch {
|
|||||||
```
|
```
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let node_ref = use_node_ref(&cx);
|
let node_ref = use_node_ref(cx);
|
||||||
use_effect(&cx, || {
|
use_effect(cx, || {
|
||||||
|
|
||||||
}, []);
|
}, []);
|
||||||
div { ref: node_ref,
|
div { ref: node_ref,
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ use std::{
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub struct Event<T: 'static + ?Sized> {
|
pub struct Event<T: 'static + ?Sized> {
|
||||||
pub(crate) data: Rc<T>,
|
/// The data associated with this event
|
||||||
|
pub data: Rc<T>,
|
||||||
pub(crate) propogates: Rc<Cell<bool>>,
|
pub(crate) propogates: Rc<Cell<bool>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -514,6 +514,14 @@ impl<'a> IntoTemplate<'a> for VNode<'a> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl<'a> IntoTemplate<'a> for Element<'a> {
|
||||||
|
fn into_template(self, _cx: &'a ScopeState) -> VNode<'a> {
|
||||||
|
match self {
|
||||||
|
Ok(val) => val.into_template(_cx),
|
||||||
|
_ => VNode::empty().unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
impl<'a, 'b> IntoTemplate<'a> for LazyNodes<'a, 'b> {
|
impl<'a, 'b> IntoTemplate<'a> for LazyNodes<'a, 'b> {
|
||||||
fn into_template(self, cx: &'a ScopeState) -> VNode<'a> {
|
fn into_template(self, cx: &'a ScopeState) -> VNode<'a> {
|
||||||
self.call(cx)
|
self.call(cx)
|
||||||
|
|||||||
@@ -21,9 +21,12 @@ pub fn use_window(cx: &ScopeState) -> &DesktopContext {
|
|||||||
|
|
||||||
/// Get a closure that executes any JavaScript in the WebView context.
|
/// Get a closure that executes any JavaScript in the WebView context.
|
||||||
pub fn use_eval(cx: &ScopeState) -> &Rc<dyn Fn(String)> {
|
pub fn use_eval(cx: &ScopeState) -> &Rc<dyn Fn(String)> {
|
||||||
let desktop = use_window(cx).clone();
|
let desktop = use_window(cx);
|
||||||
|
|
||||||
&*cx.use_hook(|| Rc::new(move |script| desktop.eval(script)) as Rc<dyn Fn(String)>)
|
&*cx.use_hook(|| {
|
||||||
|
let desktop = desktop.clone();
|
||||||
|
Rc::new(move |script| desktop.eval(script))
|
||||||
|
} as Rc<dyn Fn(String)>)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An imperative interface to the current window.
|
/// An imperative interface to the current window.
|
||||||
|
|||||||
@@ -4,26 +4,26 @@ use rand::prelude::*;
|
|||||||
fn main() {
|
fn main() {
|
||||||
let mut dom = VirtualDom::new(app);
|
let mut dom = VirtualDom::new(app);
|
||||||
|
|
||||||
dom.rebuild();
|
_ = dom.rebuild();
|
||||||
|
|
||||||
for _ in 0..1000 {
|
for _ in 0..1000 {
|
||||||
dom.rebuild();
|
_ = dom.rebuild();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let mut rng = SmallRng::from_entropy();
|
let mut rng = SmallRng::from_entropy();
|
||||||
|
|
||||||
render! (
|
cx.render(rsx! (
|
||||||
table {
|
table {
|
||||||
tbody {
|
tbody {
|
||||||
(0..10_000_usize).map(|f| {
|
(0..10_000_usize).map(|f| {
|
||||||
let label = Label::new(&mut rng);
|
let label = Label::new(&mut rng);
|
||||||
rsx!( Row { row_id: f, label: label } )
|
rsx!( table_row { row_id: f, label: label } )
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Props)]
|
#[derive(PartialEq, Props)]
|
||||||
@@ -31,9 +31,9 @@ struct RowProps {
|
|||||||
row_id: usize,
|
row_id: usize,
|
||||||
label: Label,
|
label: Label,
|
||||||
}
|
}
|
||||||
fn Row(cx: Scope<RowProps>) -> Element {
|
fn table_row(cx: Scope<RowProps>) -> Element {
|
||||||
let [adj, col, noun] = cx.props.label.0;
|
let [adj, col, noun] = cx.props.label.0;
|
||||||
render! {
|
cx.render(rsx! {
|
||||||
tr {
|
tr {
|
||||||
td { class:"col-md-1", "{cx.props.row_id}" }
|
td { class:"col-md-1", "{cx.props.row_id}" }
|
||||||
td { class:"col-md-1", onclick: move |_| { /* run onselect */ },
|
td { class:"col-md-1", onclick: move |_| { /* run onselect */ },
|
||||||
@@ -46,7 +46,7 @@ fn Row(cx: Scope<RowProps>) -> Element {
|
|||||||
}
|
}
|
||||||
td { class: "col-md-6" }
|
td { class: "col-md-6" }
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ From anywhere in our app, we can read our the value of our atom:
|
|||||||
|
|
||||||
```rust, ignore
|
```rust, ignore
|
||||||
fn NameCard(cx: Scope) -> Element {
|
fn NameCard(cx: Scope) -> Element {
|
||||||
let name = use_read(&cx, NAME);
|
let name = use_read(cx, NAME);
|
||||||
cx.render(rsx!{ h1 { "Hello, {name}"} })
|
cx.render(rsx!{ h1 { "Hello, {name}"} })
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -53,7 +53,7 @@ We can also set the value of our atom, also from anywhere in our app:
|
|||||||
|
|
||||||
```rust, ignore
|
```rust, ignore
|
||||||
fn NameCard(cx: Scope) -> Element {
|
fn NameCard(cx: Scope) -> Element {
|
||||||
let set_name = use_set(&cx, NAME);
|
let set_name = use_set(cx, NAME);
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
button {
|
button {
|
||||||
onclick: move |_| set_name("Fermi"),
|
onclick: move |_| set_name("Fermi"),
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ use std::{
|
|||||||
/// static COUNT: Atom<u32> = |_| 0;
|
/// static COUNT: Atom<u32> = |_| 0;
|
||||||
///
|
///
|
||||||
/// fn Example(cx: Scope) -> Element {
|
/// fn Example(cx: Scope) -> Element {
|
||||||
/// let mut count = use_atom_state(&cx, COUNT);
|
/// let mut count = use_atom_state(cx, COUNT);
|
||||||
///
|
///
|
||||||
/// cx.render(rsx! {
|
/// cx.render(rsx! {
|
||||||
/// div {
|
/// div {
|
||||||
@@ -74,7 +74,7 @@ impl<T: 'static> AtomState<T> {
|
|||||||
///
|
///
|
||||||
/// ```rust, ignore
|
/// ```rust, ignore
|
||||||
/// fn component(cx: Scope) -> Element {
|
/// fn component(cx: Scope) -> Element {
|
||||||
/// let count = use_state(&cx, || 0);
|
/// let count = use_state(cx, || 0);
|
||||||
/// cx.spawn({
|
/// cx.spawn({
|
||||||
/// let set_count = count.to_owned();
|
/// let set_count = count.to_owned();
|
||||||
/// async move {
|
/// async move {
|
||||||
@@ -101,7 +101,7 @@ impl<T: 'static> AtomState<T> {
|
|||||||
///
|
///
|
||||||
/// ```rust, ignore
|
/// ```rust, ignore
|
||||||
/// fn component(cx: Scope) -> Element {
|
/// fn component(cx: Scope) -> Element {
|
||||||
/// let value = use_state(&cx, || 0);
|
/// let value = use_state(cx, || 0);
|
||||||
///
|
///
|
||||||
/// rsx!{
|
/// rsx!{
|
||||||
/// Component {
|
/// Component {
|
||||||
@@ -128,7 +128,7 @@ impl<T: 'static> AtomState<T> {
|
|||||||
/// # use dioxus_core::prelude::*;
|
/// # use dioxus_core::prelude::*;
|
||||||
/// # use dioxus_hooks::*;
|
/// # use dioxus_hooks::*;
|
||||||
/// fn component(cx: Scope) -> Element {
|
/// fn component(cx: Scope) -> Element {
|
||||||
/// let value = use_state(&cx, || 0);
|
/// let value = use_state(cx, || 0);
|
||||||
///
|
///
|
||||||
/// // to increment the value
|
/// // to increment the value
|
||||||
/// value.modify(|v| v + 1);
|
/// value.modify(|v| v + 1);
|
||||||
@@ -168,7 +168,7 @@ impl<T: 'static> AtomState<T> {
|
|||||||
/// # use dioxus_core::prelude::*;
|
/// # use dioxus_core::prelude::*;
|
||||||
/// # use dioxus_hooks::*;
|
/// # use dioxus_hooks::*;
|
||||||
/// fn component(cx: Scope) -> Element {
|
/// fn component(cx: Scope) -> Element {
|
||||||
/// let value = use_state(&cx, || 0);
|
/// let value = use_state(cx, || 0);
|
||||||
///
|
///
|
||||||
/// let as_rc = value.get();
|
/// let as_rc = value.get();
|
||||||
/// assert_eq!(as_rc.as_ref(), &0);
|
/// assert_eq!(as_rc.as_ref(), &0);
|
||||||
@@ -190,7 +190,7 @@ impl<T: 'static> AtomState<T> {
|
|||||||
///
|
///
|
||||||
/// ```rust, ignore
|
/// ```rust, ignore
|
||||||
/// fn component(cx: Scope) -> Element {
|
/// fn component(cx: Scope) -> Element {
|
||||||
/// let count = use_state(&cx, || 0);
|
/// let count = use_state(cx, || 0);
|
||||||
/// cx.spawn({
|
/// cx.spawn({
|
||||||
/// let count = count.to_owned();
|
/// let count = count.to_owned();
|
||||||
/// async move {
|
/// async move {
|
||||||
@@ -220,7 +220,7 @@ impl<T: Clone> AtomState<T> {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// let val = use_state(&cx, || 0);
|
/// let val = use_state(cx, || 0);
|
||||||
///
|
///
|
||||||
/// val.with_mut(|v| *v = 1);
|
/// val.with_mut(|v| *v = 1);
|
||||||
/// ```
|
/// ```
|
||||||
@@ -243,7 +243,7 @@ impl<T: Clone> AtomState<T> {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// let val = use_state(&cx, || 0);
|
/// let val = use_state(cx, || 0);
|
||||||
///
|
///
|
||||||
/// *val.make_mut() += 1;
|
/// *val.make_mut() += 1;
|
||||||
/// ```
|
/// ```
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ You can always use it "normally" with the `split` method:
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
// Rusty-smart-pointer usage:
|
// Rusty-smart-pointer usage:
|
||||||
let value = use_state(&cx, || 10);
|
let value = use_state(cx, || 10);
|
||||||
|
|
||||||
// "Classic" usage:
|
// "Classic" usage:
|
||||||
let (value, set_value) = use_state(&cx, || 0).split();
|
let (value, set_value) = use_state(cx, || 0).split();
|
||||||
```
|
```
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// let (data) = use_ref(&cx, || {});
|
/// let (data) = use_ref(cx, || {});
|
||||||
///
|
///
|
||||||
/// let handle_thing = move |_| {
|
/// let handle_thing = move |_| {
|
||||||
/// to_owned![data]
|
/// to_owned![data]
|
||||||
@@ -30,8 +30,8 @@ pub use usestate::{use_state, UseState};
|
|||||||
mod useref;
|
mod useref;
|
||||||
pub use useref::*;
|
pub use useref::*;
|
||||||
|
|
||||||
// mod use_shared_state;
|
mod use_shared_state;
|
||||||
// pub use use_shared_state::*;
|
pub use use_shared_state::*;
|
||||||
|
|
||||||
mod usecoroutine;
|
mod usecoroutine;
|
||||||
pub use usecoroutine::*;
|
pub use usecoroutine::*;
|
||||||
|
|||||||
@@ -60,10 +60,10 @@ impl<T> ProvidedStateInner<T> {
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
pub fn use_context<T: 'static>(cx: &ScopeState) -> Option<UseSharedState<T>> {
|
pub fn use_shared_state<T: 'static>(cx: &ScopeState) -> Option<UseSharedState<T>> {
|
||||||
let state = cx.use_hook(|| {
|
let state = cx.use_hook(|| {
|
||||||
let scope_id = cx.scope_id();
|
let scope_id = cx.scope_id();
|
||||||
let root = cx.consume_context::<ProvidedState<T>>().cloned();
|
let root = cx.consume_context::<ProvidedState<T>>();
|
||||||
|
|
||||||
if let Some(root) = root.as_ref() {
|
if let Some(root) = root.as_ref() {
|
||||||
root.borrow_mut().consumers.insert(scope_id);
|
root.borrow_mut().consumers.insert(scope_id);
|
||||||
@@ -165,14 +165,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Provide some state for components down the hierarchy to consume without having to drill props.
|
/// Provide some state for components down the hierarchy to consume without having to drill props.
|
||||||
///
|
pub fn use_shared_state_provider<T: 'static>(cx: &ScopeState, f: impl FnOnce() -> T) {
|
||||||
///
|
|
||||||
///
|
|
||||||
///
|
|
||||||
///
|
|
||||||
///
|
|
||||||
///
|
|
||||||
pub fn use_context_provider<T: 'static>(cx: &ScopeState, f: impl FnOnce() -> T) {
|
|
||||||
cx.use_hook(|| {
|
cx.use_hook(|| {
|
||||||
let state: ProvidedState<T> = Rc::new(RefCell::new(ProvidedStateInner {
|
let state: ProvidedState<T> = Rc::new(RefCell::new(ProvidedStateInner {
|
||||||
value: Rc::new(RefCell::new(f())),
|
value: Rc::new(RefCell::new(f())),
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ This is moderately efficient because the fields of the map are moved, but the da
|
|||||||
However, if you used similar approach with Dioxus:
|
However, if you used similar approach with Dioxus:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let (map, set_map) = use_state(&cx, || HashMap::new());
|
let (map, set_map) = use_state(cx, || HashMap::new());
|
||||||
set_map({
|
set_map({
|
||||||
let mut newmap = map.clone();
|
let mut newmap = map.clone();
|
||||||
newmap.set(key, value);
|
newmap.set(key, value);
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
use dioxus_core::ScopeState;
|
use dioxus_core::ScopeState;
|
||||||
|
|
||||||
/// Consume some context in the tree, providing a sharable handle to the value
|
/// Consume some context in the tree, providing a sharable handle to the value
|
||||||
|
///
|
||||||
|
/// Does not regenerate the value if the value is changed at the parent.
|
||||||
pub fn use_context<T: 'static + Clone>(cx: &ScopeState) -> Option<&T> {
|
pub fn use_context<T: 'static + Clone>(cx: &ScopeState) -> Option<&T> {
|
||||||
cx.use_hook(|| cx.consume_context::<T>()).as_ref()
|
cx.use_hook(|| cx.consume_context::<T>()).as_ref()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ use dioxus_core::{ScopeState, TaskId};
|
|||||||
pub use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
|
pub use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
|
||||||
use crate::{use_context, use_context_provider};
|
|
||||||
|
|
||||||
/// Maintain a handle over a future that can be paused, resumed, and canceled.
|
/// Maintain a handle over a future that can be paused, resumed, and canceled.
|
||||||
///
|
///
|
||||||
/// This is an upgraded form of [`use_future`] with an integrated channel system.
|
/// This is an upgraded form of [`use_future`] with an integrated channel system.
|
||||||
@@ -44,7 +42,7 @@ use crate::{use_context, use_context_provider};
|
|||||||
/// Stop,
|
/// Stop,
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// let chat_client = use_coroutine(&cx, |rx: UnboundedReceiver<Action>| async move {
|
/// let chat_client = use_coroutine(cx, |rx: UnboundedReceiver<Action>| async move {
|
||||||
/// while let Some(action) = rx.next().await {
|
/// while let Some(action) = rx.next().await {
|
||||||
/// match action {
|
/// match action {
|
||||||
/// Action::Start => {}
|
/// Action::Start => {}
|
||||||
@@ -67,10 +65,10 @@ where
|
|||||||
G: FnOnce(UnboundedReceiver<M>) -> F,
|
G: FnOnce(UnboundedReceiver<M>) -> F,
|
||||||
F: Future<Output = ()> + 'static,
|
F: Future<Output = ()> + 'static,
|
||||||
{
|
{
|
||||||
use_context_provider(cx, || {
|
cx.use_hook(|| {
|
||||||
let (tx, rx) = futures_channel::mpsc::unbounded();
|
let (tx, rx) = futures_channel::mpsc::unbounded();
|
||||||
let task = cx.push_future(init(rx));
|
let task = cx.push_future(init(rx));
|
||||||
Coroutine { tx, task }
|
cx.provide_context(Coroutine { tx, task })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +76,8 @@ where
|
|||||||
///
|
///
|
||||||
/// See the docs for [`use_coroutine`] for more details.
|
/// See the docs for [`use_coroutine`] for more details.
|
||||||
pub fn use_coroutine_handle<M: 'static>(cx: &ScopeState) -> Option<&Coroutine<M>> {
|
pub fn use_coroutine_handle<M: 'static>(cx: &ScopeState) -> Option<&Coroutine<M>> {
|
||||||
use_context::<Coroutine<M>>(cx)
|
cx.use_hook(|| cx.consume_context::<Coroutine<M>>())
|
||||||
|
.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Coroutine<T> {
|
pub struct Coroutine<T> {
|
||||||
@@ -119,15 +118,15 @@ mod tests {
|
|||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
|
|
||||||
fn app(cx: Scope, name: String) -> Element {
|
fn app(cx: Scope, name: String) -> Element {
|
||||||
let task = use_coroutine(&cx, |mut rx: UnboundedReceiver<i32>| async move {
|
let task = use_coroutine(cx, |mut rx: UnboundedReceiver<i32>| async move {
|
||||||
while let Some(msg) = rx.next().await {
|
while let Some(msg) = rx.next().await {
|
||||||
println!("got message: {}", msg);
|
println!("got message: {}", msg);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let task2 = use_coroutine(&cx, view_task);
|
let task2 = use_coroutine(cx, view_task);
|
||||||
|
|
||||||
let task3 = use_coroutine(&cx, |rx| complex_task(rx, 10));
|
let task3 = use_coroutine(cx, |rx| complex_task(rx, 10));
|
||||||
|
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use crate::UseFutureDep;
|
|||||||
///
|
///
|
||||||
/// #[inline_props]
|
/// #[inline_props]
|
||||||
/// fn app(cx: Scope, name: &str) -> Element {
|
/// fn app(cx: Scope, name: &str) -> Element {
|
||||||
/// use_effect(&cx, (name,), |(name,)| async move {
|
/// use_effect(cx, (name,), |(name,)| async move {
|
||||||
/// set_title(name);
|
/// set_title(name);
|
||||||
/// }))
|
/// }))
|
||||||
/// }
|
/// }
|
||||||
@@ -72,17 +72,17 @@ mod tests {
|
|||||||
|
|
||||||
fn app(cx: Scope<MyProps>) -> Element {
|
fn app(cx: Scope<MyProps>) -> Element {
|
||||||
// should only ever run once
|
// should only ever run once
|
||||||
use_effect(&cx, (), |_| async move {
|
use_effect(cx, (), |_| async move {
|
||||||
//
|
//
|
||||||
});
|
});
|
||||||
|
|
||||||
// runs when a is changed
|
// runs when a is changed
|
||||||
use_effect(&cx, (&cx.props.a,), |(a,)| async move {
|
use_effect(cx, (&cx.props.a,), |(a,)| async move {
|
||||||
//
|
//
|
||||||
});
|
});
|
||||||
|
|
||||||
// runs when a or b is changed
|
// runs when a or b is changed
|
||||||
use_effect(&cx, (&cx.props.a, &cx.props.b), |(a, b)| async move {
|
use_effect(cx, (&cx.props.a, &cx.props.b), |(a, b)| async move {
|
||||||
//
|
//
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ use std::{
|
|||||||
///
|
///
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// const Example: Component = |cx| {
|
/// const Example: Component = |cx| {
|
||||||
/// let count = use_state(&cx, || 0);
|
/// let count = use_state(cx, || 0);
|
||||||
///
|
///
|
||||||
/// cx.render(rsx! {
|
/// cx.render(rsx! {
|
||||||
/// div {
|
/// div {
|
||||||
@@ -92,7 +92,7 @@ impl<T: 'static> UseState<T> {
|
|||||||
///
|
///
|
||||||
/// ```rust, ignore
|
/// ```rust, ignore
|
||||||
/// fn component(cx: Scope) -> Element {
|
/// fn component(cx: Scope) -> Element {
|
||||||
/// let count = use_state(&cx, || 0);
|
/// let count = use_state(cx, || 0);
|
||||||
/// cx.spawn({
|
/// cx.spawn({
|
||||||
/// let set_count = count.to_owned();
|
/// let set_count = count.to_owned();
|
||||||
/// async move {
|
/// async move {
|
||||||
@@ -119,7 +119,7 @@ impl<T: 'static> UseState<T> {
|
|||||||
///
|
///
|
||||||
/// ```rust, ignore
|
/// ```rust, ignore
|
||||||
/// fn component(cx: Scope) -> Element {
|
/// fn component(cx: Scope) -> Element {
|
||||||
/// let value = use_state(&cx, || 0);
|
/// let value = use_state(cx, || 0);
|
||||||
///
|
///
|
||||||
/// rsx!{
|
/// rsx!{
|
||||||
/// Component {
|
/// Component {
|
||||||
@@ -144,7 +144,7 @@ impl<T: 'static> UseState<T> {
|
|||||||
/// # use dioxus_core::prelude::*;
|
/// # use dioxus_core::prelude::*;
|
||||||
/// # use dioxus_hooks::*;
|
/// # use dioxus_hooks::*;
|
||||||
/// fn component(cx: Scope) -> Element {
|
/// fn component(cx: Scope) -> Element {
|
||||||
/// let value = use_state(&cx, || 0);
|
/// let value = use_state(cx, || 0);
|
||||||
///
|
///
|
||||||
/// // to increment the value
|
/// // to increment the value
|
||||||
/// value.modify(|v| v + 1);
|
/// value.modify(|v| v + 1);
|
||||||
@@ -185,7 +185,7 @@ impl<T: 'static> UseState<T> {
|
|||||||
/// # use dioxus_core::prelude::*;
|
/// # use dioxus_core::prelude::*;
|
||||||
/// # use dioxus_hooks::*;
|
/// # use dioxus_hooks::*;
|
||||||
/// fn component(cx: Scope) -> Element {
|
/// fn component(cx: Scope) -> Element {
|
||||||
/// let value = use_state(&cx, || 0);
|
/// let value = use_state(cx, || 0);
|
||||||
///
|
///
|
||||||
/// let as_rc = value.get();
|
/// let as_rc = value.get();
|
||||||
/// assert_eq!(as_rc.as_ref(), &0);
|
/// assert_eq!(as_rc.as_ref(), &0);
|
||||||
@@ -207,7 +207,7 @@ impl<T: 'static> UseState<T> {
|
|||||||
///
|
///
|
||||||
/// ```rust, ignore
|
/// ```rust, ignore
|
||||||
/// fn component(cx: Scope) -> Element {
|
/// fn component(cx: Scope) -> Element {
|
||||||
/// let count = use_state(&cx, || 0);
|
/// let count = use_state(cx, || 0);
|
||||||
/// cx.spawn({
|
/// cx.spawn({
|
||||||
/// let count = count.to_owned();
|
/// let count = count.to_owned();
|
||||||
/// async move {
|
/// async move {
|
||||||
@@ -237,7 +237,7 @@ impl<T: Clone> UseState<T> {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust, ignore
|
/// ```rust, ignore
|
||||||
/// let val = use_state(&cx, || 0);
|
/// let val = use_state(cx, || 0);
|
||||||
///
|
///
|
||||||
/// val.with_mut(|v| *v = 1);
|
/// val.with_mut(|v| *v = 1);
|
||||||
/// ```
|
/// ```
|
||||||
@@ -269,7 +269,7 @@ impl<T: Clone> UseState<T> {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust, ignore
|
/// ```rust, ignore
|
||||||
/// let val = use_state(&cx, || 0);
|
/// let val = use_state(cx, || 0);
|
||||||
///
|
///
|
||||||
/// *val.make_mut() += 1;
|
/// *val.make_mut() += 1;
|
||||||
/// ```
|
/// ```
|
||||||
@@ -448,7 +448,7 @@ impl<T: Div<Output = T> + Copy> std::ops::DivAssign<T> for UseState<T> {
|
|||||||
fn api_makes_sense() {
|
fn api_makes_sense() {
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let val = use_state(&cx, || 0);
|
let val = use_state(cx, || 0);
|
||||||
|
|
||||||
val.set(0);
|
val.set(0);
|
||||||
val.modify(|v| v + 1);
|
val.modify(|v| v + 1);
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
mod keys;
|
|
||||||
pub use keys::*;
|
|
||||||
|
|
||||||
macro_rules! impl_event {
|
macro_rules! impl_event {
|
||||||
(
|
(
|
||||||
$data:ty;
|
$data:ty;
|
||||||
|
|||||||
@@ -1,370 +0,0 @@
|
|||||||
#[cfg_attr(
|
|
||||||
feature = "serialize",
|
|
||||||
derive(serde_repr::Serialize_repr, serde_repr::Deserialize_repr)
|
|
||||||
)]
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
||||||
#[repr(u8)]
|
|
||||||
pub enum KeyCode {
|
|
||||||
// That key has no keycode, = 0
|
|
||||||
// break, = 3
|
|
||||||
// backspace / delete, = 8
|
|
||||||
// tab, = 9
|
|
||||||
// clear, = 12
|
|
||||||
// enter, = 13
|
|
||||||
// shift, = 16
|
|
||||||
// ctrl, = 17
|
|
||||||
// alt, = 18
|
|
||||||
// pause/break, = 19
|
|
||||||
// caps lock, = 20
|
|
||||||
// hangul, = 21
|
|
||||||
// hanja, = 25
|
|
||||||
// escape, = 27
|
|
||||||
// conversion, = 28
|
|
||||||
// non-conversion, = 29
|
|
||||||
// spacebar, = 32
|
|
||||||
// page up, = 33
|
|
||||||
// page down, = 34
|
|
||||||
// end, = 35
|
|
||||||
// home, = 36
|
|
||||||
// left arrow, = 37
|
|
||||||
// up arrow, = 38
|
|
||||||
// right arrow, = 39
|
|
||||||
// down arrow, = 40
|
|
||||||
// select, = 41
|
|
||||||
// print, = 42
|
|
||||||
// execute, = 43
|
|
||||||
// Print Screen, = 44
|
|
||||||
// insert, = 45
|
|
||||||
// delete, = 46
|
|
||||||
// help, = 47
|
|
||||||
// 0, = 48
|
|
||||||
// 1, = 49
|
|
||||||
// 2, = 50
|
|
||||||
// 3, = 51
|
|
||||||
// 4, = 52
|
|
||||||
// 5, = 53
|
|
||||||
// 6, = 54
|
|
||||||
// 7, = 55
|
|
||||||
// 8, = 56
|
|
||||||
// 9, = 57
|
|
||||||
// :, = 58
|
|
||||||
// semicolon (firefox), equals, = 59
|
|
||||||
// <, = 60
|
|
||||||
// equals (firefox), = 61
|
|
||||||
// ß, = 63
|
|
||||||
// @ (firefox), = 64
|
|
||||||
// a, = 65
|
|
||||||
// b, = 66
|
|
||||||
// c, = 67
|
|
||||||
// d, = 68
|
|
||||||
// e, = 69
|
|
||||||
// f, = 70
|
|
||||||
// g, = 71
|
|
||||||
// h, = 72
|
|
||||||
// i, = 73
|
|
||||||
// j, = 74
|
|
||||||
// k, = 75
|
|
||||||
// l, = 76
|
|
||||||
// m, = 77
|
|
||||||
// n, = 78
|
|
||||||
// o, = 79
|
|
||||||
// p, = 80
|
|
||||||
// q, = 81
|
|
||||||
// r, = 82
|
|
||||||
// s, = 83
|
|
||||||
// t, = 84
|
|
||||||
// u, = 85
|
|
||||||
// v, = 86
|
|
||||||
// w, = 87
|
|
||||||
// x, = 88
|
|
||||||
// y, = 89
|
|
||||||
// z, = 90
|
|
||||||
// Windows Key / Left ⌘ / Chromebook Search key, = 91
|
|
||||||
// right window key, = 92
|
|
||||||
// Windows Menu / Right ⌘, = 93
|
|
||||||
// sleep, = 95
|
|
||||||
// numpad 0, = 96
|
|
||||||
// numpad 1, = 97
|
|
||||||
// numpad 2, = 98
|
|
||||||
// numpad 3, = 99
|
|
||||||
// numpad 4, = 100
|
|
||||||
// numpad 5, = 101
|
|
||||||
// numpad 6, = 102
|
|
||||||
// numpad 7, = 103
|
|
||||||
// numpad 8, = 104
|
|
||||||
// numpad 9, = 105
|
|
||||||
// multiply, = 106
|
|
||||||
// add, = 107
|
|
||||||
// numpad period (firefox), = 108
|
|
||||||
// subtract, = 109
|
|
||||||
// decimal point, = 110
|
|
||||||
// divide, = 111
|
|
||||||
// f1, = 112
|
|
||||||
// f2, = 113
|
|
||||||
// f3, = 114
|
|
||||||
// f4, = 115
|
|
||||||
// f5, = 116
|
|
||||||
// f6, = 117
|
|
||||||
// f7, = 118
|
|
||||||
// f8, = 119
|
|
||||||
// f9, = 120
|
|
||||||
// f10, = 121
|
|
||||||
// f11, = 122
|
|
||||||
// f12, = 123
|
|
||||||
// f13, = 124
|
|
||||||
// f14, = 125
|
|
||||||
// f15, = 126
|
|
||||||
// f16, = 127
|
|
||||||
// f17, = 128
|
|
||||||
// f18, = 129
|
|
||||||
// f19, = 130
|
|
||||||
// f20, = 131
|
|
||||||
// f21, = 132
|
|
||||||
// f22, = 133
|
|
||||||
// f23, = 134
|
|
||||||
// f24, = 135
|
|
||||||
// f25, = 136
|
|
||||||
// f26, = 137
|
|
||||||
// f27, = 138
|
|
||||||
// f28, = 139
|
|
||||||
// f29, = 140
|
|
||||||
// f30, = 141
|
|
||||||
// f31, = 142
|
|
||||||
// f32, = 143
|
|
||||||
// num lock, = 144
|
|
||||||
// scroll lock, = 145
|
|
||||||
// airplane mode, = 151
|
|
||||||
// ^, = 160
|
|
||||||
// !, = 161
|
|
||||||
// ؛ (arabic semicolon), = 162
|
|
||||||
// #, = 163
|
|
||||||
// $, = 164
|
|
||||||
// ù, = 165
|
|
||||||
// page backward, = 166
|
|
||||||
// page forward, = 167
|
|
||||||
// refresh, = 168
|
|
||||||
// closing paren (AZERTY), = 169
|
|
||||||
// *, = 170
|
|
||||||
// ~ + * key, = 171
|
|
||||||
// home key, = 172
|
|
||||||
// minus (firefox), mute/unmute, = 173
|
|
||||||
// decrease volume level, = 174
|
|
||||||
// increase volume level, = 175
|
|
||||||
// next, = 176
|
|
||||||
// previous, = 177
|
|
||||||
// stop, = 178
|
|
||||||
// play/pause, = 179
|
|
||||||
// e-mail, = 180
|
|
||||||
// mute/unmute (firefox), = 181
|
|
||||||
// decrease volume level (firefox), = 182
|
|
||||||
// increase volume level (firefox), = 183
|
|
||||||
// semi-colon / ñ, = 186
|
|
||||||
// equal sign, = 187
|
|
||||||
// comma, = 188
|
|
||||||
// dash, = 189
|
|
||||||
// period, = 190
|
|
||||||
// forward slash / ç, = 191
|
|
||||||
// grave accent / ñ / æ / ö, = 192
|
|
||||||
// ?, / or °, = 193
|
|
||||||
// numpad period (chrome), = 194
|
|
||||||
// open bracket, = 219
|
|
||||||
// back slash, = 220
|
|
||||||
// close bracket / å, = 221
|
|
||||||
// single quote / ø / ä, = 222
|
|
||||||
// `, = 223
|
|
||||||
// left or right ⌘ key (firefox), = 224
|
|
||||||
// altgr, = 225
|
|
||||||
// < /git >, left back slash, = 226
|
|
||||||
// GNOME Compose Key, = 230
|
|
||||||
// ç, = 231
|
|
||||||
// XF86Forward, = 233
|
|
||||||
// XF86Back, = 234
|
|
||||||
// non-conversion, = 235
|
|
||||||
// alphanumeric, = 240
|
|
||||||
// hiragana/katakana, = 242
|
|
||||||
// half-width/full-width, = 243
|
|
||||||
// kanji, = 244
|
|
||||||
// unlock trackpad (Chrome/Edge), = 251
|
|
||||||
// toggle touchpad, = 255
|
|
||||||
NA = 0,
|
|
||||||
Break = 3,
|
|
||||||
Backspace = 8,
|
|
||||||
Tab = 9,
|
|
||||||
Clear = 12,
|
|
||||||
Enter = 13,
|
|
||||||
Shift = 16,
|
|
||||||
Ctrl = 17,
|
|
||||||
Alt = 18,
|
|
||||||
Pause = 19,
|
|
||||||
CapsLock = 20,
|
|
||||||
// hangul, = 21
|
|
||||||
// hanja, = 25
|
|
||||||
Escape = 27,
|
|
||||||
// conversion, = 28
|
|
||||||
// non-conversion, = 29
|
|
||||||
Space = 32,
|
|
||||||
PageUp = 33,
|
|
||||||
PageDown = 34,
|
|
||||||
End = 35,
|
|
||||||
Home = 36,
|
|
||||||
LeftArrow = 37,
|
|
||||||
UpArrow = 38,
|
|
||||||
RightArrow = 39,
|
|
||||||
DownArrow = 40,
|
|
||||||
// select, = 41
|
|
||||||
// print, = 42
|
|
||||||
// execute, = 43
|
|
||||||
// Print Screen, = 44
|
|
||||||
Insert = 45,
|
|
||||||
Delete = 46,
|
|
||||||
// help, = 47
|
|
||||||
Num0 = 48,
|
|
||||||
Num1 = 49,
|
|
||||||
Num2 = 50,
|
|
||||||
Num3 = 51,
|
|
||||||
Num4 = 52,
|
|
||||||
Num5 = 53,
|
|
||||||
Num6 = 54,
|
|
||||||
Num7 = 55,
|
|
||||||
Num8 = 56,
|
|
||||||
Num9 = 57,
|
|
||||||
// :, = 58
|
|
||||||
// semicolon (firefox), equals, = 59
|
|
||||||
// <, = 60
|
|
||||||
// equals (firefox), = 61
|
|
||||||
// ß, = 63
|
|
||||||
// @ (firefox), = 64
|
|
||||||
A = 65,
|
|
||||||
B = 66,
|
|
||||||
C = 67,
|
|
||||||
D = 68,
|
|
||||||
E = 69,
|
|
||||||
F = 70,
|
|
||||||
G = 71,
|
|
||||||
H = 72,
|
|
||||||
I = 73,
|
|
||||||
J = 74,
|
|
||||||
K = 75,
|
|
||||||
L = 76,
|
|
||||||
M = 77,
|
|
||||||
N = 78,
|
|
||||||
O = 79,
|
|
||||||
P = 80,
|
|
||||||
Q = 81,
|
|
||||||
R = 82,
|
|
||||||
S = 83,
|
|
||||||
T = 84,
|
|
||||||
U = 85,
|
|
||||||
V = 86,
|
|
||||||
W = 87,
|
|
||||||
X = 88,
|
|
||||||
Y = 89,
|
|
||||||
Z = 90,
|
|
||||||
LeftWindow = 91,
|
|
||||||
RightWindow = 92,
|
|
||||||
SelectKey = 93,
|
|
||||||
Numpad0 = 96,
|
|
||||||
Numpad1 = 97,
|
|
||||||
Numpad2 = 98,
|
|
||||||
Numpad3 = 99,
|
|
||||||
Numpad4 = 100,
|
|
||||||
Numpad5 = 101,
|
|
||||||
Numpad6 = 102,
|
|
||||||
Numpad7 = 103,
|
|
||||||
Numpad8 = 104,
|
|
||||||
Numpad9 = 105,
|
|
||||||
Multiply = 106,
|
|
||||||
Add = 107,
|
|
||||||
Subtract = 109,
|
|
||||||
DecimalPoint = 110,
|
|
||||||
Divide = 111,
|
|
||||||
F1 = 112,
|
|
||||||
F2 = 113,
|
|
||||||
F3 = 114,
|
|
||||||
F4 = 115,
|
|
||||||
F5 = 116,
|
|
||||||
F6 = 117,
|
|
||||||
F7 = 118,
|
|
||||||
F8 = 119,
|
|
||||||
F9 = 120,
|
|
||||||
F10 = 121,
|
|
||||||
F11 = 122,
|
|
||||||
F12 = 123,
|
|
||||||
// f13, = 124
|
|
||||||
// f14, = 125
|
|
||||||
// f15, = 126
|
|
||||||
// f16, = 127
|
|
||||||
// f17, = 128
|
|
||||||
// f18, = 129
|
|
||||||
// f19, = 130
|
|
||||||
// f20, = 131
|
|
||||||
// f21, = 132
|
|
||||||
// f22, = 133
|
|
||||||
// f23, = 134
|
|
||||||
// f24, = 135
|
|
||||||
// f25, = 136
|
|
||||||
// f26, = 137
|
|
||||||
// f27, = 138
|
|
||||||
// f28, = 139
|
|
||||||
// f29, = 140
|
|
||||||
// f30, = 141
|
|
||||||
// f31, = 142
|
|
||||||
// f32, = 143
|
|
||||||
NumLock = 144,
|
|
||||||
ScrollLock = 145,
|
|
||||||
// airplane mode, = 151
|
|
||||||
// ^, = 160
|
|
||||||
// !, = 161
|
|
||||||
// ؛ (arabic semicolon), = 162
|
|
||||||
// #, = 163
|
|
||||||
// $, = 164
|
|
||||||
// ù, = 165
|
|
||||||
// page backward, = 166
|
|
||||||
// page forward, = 167
|
|
||||||
// refresh, = 168
|
|
||||||
// closing paren (AZERTY), = 169
|
|
||||||
// *, = 170
|
|
||||||
// ~ + * key, = 171
|
|
||||||
// home key, = 172
|
|
||||||
// minus (firefox), mute/unmute, = 173
|
|
||||||
// decrease volume level, = 174
|
|
||||||
// increase volume level, = 175
|
|
||||||
// next, = 176
|
|
||||||
// previous, = 177
|
|
||||||
// stop, = 178
|
|
||||||
// play/pause, = 179
|
|
||||||
// e-mail, = 180
|
|
||||||
// mute/unmute (firefox), = 181
|
|
||||||
// decrease volume level (firefox), = 182
|
|
||||||
// increase volume level (firefox), = 183
|
|
||||||
Semicolon = 186,
|
|
||||||
EqualSign = 187,
|
|
||||||
Comma = 188,
|
|
||||||
Dash = 189,
|
|
||||||
Period = 190,
|
|
||||||
ForwardSlash = 191,
|
|
||||||
GraveAccent = 192,
|
|
||||||
// ?, / or °, = 193
|
|
||||||
// numpad period (chrome), = 194
|
|
||||||
OpenBracket = 219,
|
|
||||||
BackSlash = 220,
|
|
||||||
CloseBraket = 221,
|
|
||||||
SingleQuote = 222,
|
|
||||||
// `, = 223
|
|
||||||
// left or right ⌘ key (firefox), = 224
|
|
||||||
// altgr, = 225
|
|
||||||
// < /git >, left back slash, = 226
|
|
||||||
// GNOME Compose Key, = 230
|
|
||||||
// ç, = 231
|
|
||||||
// XF86Forward, = 233
|
|
||||||
// XF86Back, = 234
|
|
||||||
// non-conversion, = 235
|
|
||||||
// alphanumeric, = 240
|
|
||||||
// hiragana/katakana, = 242
|
|
||||||
// half-width/full-width, = 243
|
|
||||||
// kanji, = 244
|
|
||||||
// unlock trackpad (Chrome/Edge), = 251
|
|
||||||
// toggle touchpad, = 255
|
|
||||||
#[cfg_attr(feature = "serialize", serde(other))]
|
|
||||||
Unknown,
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use js_sys::Function;
|
use js_sys::Function;
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
use web_sys::{Element, Node};
|
use web_sys::Element;
|
||||||
|
|
||||||
#[wasm_bindgen(module = "/src/interpreter.js")]
|
#[wasm_bindgen(module = "/src/interpreter.js")]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -18,7 +18,7 @@ extern "C" {
|
|||||||
pub fn MountToRoot(this: &Interpreter);
|
pub fn MountToRoot(this: &Interpreter);
|
||||||
|
|
||||||
#[wasm_bindgen(method)]
|
#[wasm_bindgen(method)]
|
||||||
pub fn AppendChildren(this: &Interpreter, m: u32);
|
pub fn AppendChildren(this: &Interpreter, m: u32, id: u32);
|
||||||
|
|
||||||
#[wasm_bindgen(method)]
|
#[wasm_bindgen(method)]
|
||||||
pub fn AssignId(this: &Interpreter, path: &[u8], id: u32);
|
pub fn AssignId(this: &Interpreter, path: &[u8], id: u32);
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ async fn order_shoes(mut req: WebsocketRequest) -> Response {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn App(cx: Scope) -> Element {
|
fn App(cx: Scope) -> Element {
|
||||||
let mut count = use_state(&cx, || 0);
|
let mut count = use_state(cx, || 0);
|
||||||
cx.render(rsx!(
|
cx.render(rsx!(
|
||||||
button { onclick: move |_| count += 1, "Incr" }
|
button { onclick: move |_| count += 1, "Incr" }
|
||||||
button { onclick: move |_| count -= 1, "Decr" }
|
button { onclick: move |_| count -= 1, "Decr" }
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use std::any::Any;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use dioxus_core::ElementId;
|
use dioxus_core::ElementId;
|
||||||
use dioxus_html::event_bubbles;
|
// use dioxus_html::event_bubbles;
|
||||||
use dioxus_html::events::*;
|
use dioxus_html::events::*;
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
@@ -29,7 +29,7 @@ struct ImEvent {
|
|||||||
contents: serde_json::Value,
|
contents: serde_json::Value,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trigger_from_serialized(val: serde_json::Value) -> () {
|
pub fn trigger_from_serialized(_val: serde_json::Value) {
|
||||||
todo!()
|
todo!()
|
||||||
// let ImEvent {
|
// let ImEvent {
|
||||||
// event,
|
// event,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use anymap::AnyMap;
|
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use dioxus_native_core::node_ref::*;
|
use dioxus_native_core::node_ref::*;
|
||||||
use dioxus_native_core::real_dom::*;
|
use dioxus_native_core::real_dom::*;
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
use dioxus::core::ElementId;
|
|
||||||
use dioxus::core::{AttributeValue, Mutations};
|
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use dioxus_native_core::real_dom::*;
|
use dioxus_native_core::real_dom::*;
|
||||||
use dioxus_native_core::state::{ChildDepState, NodeDepState, ParentDepState, State};
|
use dioxus_native_core::state::{ChildDepState, NodeDepState, ParentDepState, State};
|
||||||
use dioxus_native_core::tree::TreeView;
|
use dioxus_native_core::tree::TreeView;
|
||||||
use dioxus_native_core::{node_ref::*, NodeId, RealNodeId, SendAnyMap};
|
use dioxus_native_core::{node_ref::*, NodeId, SendAnyMap};
|
||||||
use dioxus_native_core_macro::State;
|
use dioxus_native_core_macro::State;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, State)]
|
#[derive(Debug, Clone, Default, State)]
|
||||||
|
|||||||
@@ -36,7 +36,9 @@ fn BlogList(cx: Scope) -> Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn BlogPost(cx: Scope) -> Element {
|
fn BlogPost(cx: Scope) -> Element {
|
||||||
let id = use_route(&cx).segment("id")?;
|
let Some(id) = use_route(cx).segment("id") else {
|
||||||
|
return cx.render(rsx! { div { "No blog post id" } })
|
||||||
|
};
|
||||||
|
|
||||||
log::trace!("rendering blog post {}", id);
|
log::trace!("rendering blog post {}", id);
|
||||||
|
|
||||||
|
|||||||
@@ -39,15 +39,15 @@ pub struct RouterProps<'a> {
|
|||||||
/// Will fallback to HashRouter is BrowserRouter is not available, or through configuration.
|
/// Will fallback to HashRouter is BrowserRouter is not available, or through configuration.
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn Router<'a>(cx: Scope<'a, RouterProps<'a>>) -> Element {
|
pub fn Router<'a>(cx: Scope<'a, RouterProps<'a>>) -> Element {
|
||||||
let svc = use_context_provider(cx, || {
|
let svc = cx.use_hook(|| {
|
||||||
RouterService::new(
|
cx.provide_context(RouterService::new(
|
||||||
cx,
|
cx,
|
||||||
RouterCfg {
|
RouterCfg {
|
||||||
base_url: cx.props.base_url.map(|s| s.to_string()),
|
base_url: cx.props.base_url.map(|s| s.to_string()),
|
||||||
active_class: cx.props.active_class.map(|s| s.to_string()),
|
active_class: cx.props.active_class.map(|s| s.to_string()),
|
||||||
initial_url: cx.props.initial_url.clone(),
|
initial_url: cx.props.initial_url.clone(),
|
||||||
},
|
},
|
||||||
)
|
))
|
||||||
});
|
});
|
||||||
|
|
||||||
// next time we run the rout_found will be filled
|
// next time we run the rout_found will be filled
|
||||||
|
|||||||
@@ -415,7 +415,7 @@ mod web {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attach_listeners(&self, svc: std::sync::Weak<crate::RouterService>) {
|
fn attach_listeners(&self, svc: std::rc::Weak<crate::RouterService>) {
|
||||||
self._listener.set(Some(EventListener::new(
|
self._listener.set(Some(EventListener::new(
|
||||||
&web_sys::window().unwrap(),
|
&web_sys::window().unwrap(),
|
||||||
"popstate",
|
"popstate",
|
||||||
|
|||||||
@@ -13,13 +13,13 @@ fn simple_test() {
|
|||||||
fn main() {
|
fn main() {
|
||||||
console_error_panic_hook::set_once();
|
console_error_panic_hook::set_once();
|
||||||
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
||||||
dioxus_web::launch(APP);
|
dioxus_web::launch(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
static APP: Component = |cx| {
|
fn app(cx: Scope) -> Element {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
Router {
|
Router {
|
||||||
onchange: move |route: RouterService| log::trace!("route changed to {:?}", route.current_location()),
|
onchange: move |router: RouterContext| log::trace!("route changed to {:?}", router.current_location()),
|
||||||
active_class: "is-active",
|
active_class: "is-active",
|
||||||
Route { to: "/", Home {} }
|
Route { to: "/", Home {} }
|
||||||
Route { to: "blog"
|
Route { to: "blog"
|
||||||
@@ -28,7 +28,7 @@ fn simple_test() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
fn Home(cx: Scope) -> Element {
|
fn Home(cx: Scope) -> Element {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
@@ -47,12 +47,10 @@ fn simple_test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn BlogPost(cx: Scope) -> Element {
|
fn BlogPost(cx: Scope) -> Element {
|
||||||
let _id = use_route(&cx).parse_segment::<usize>("id")?;
|
let _id = use_route(cx).parse_segment::<usize>("id").unwrap();
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div { }
|
||||||
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ For any route, you can get a handle the current route with the `use_route` hook.
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn Title(cx: Scope) -> Element {
|
fn Title(cx: Scope) -> Element {
|
||||||
let route = use_route(&cx);
|
let route = use_route(cx);
|
||||||
|
|
||||||
assert_eq!(route.segments(), &["dogs", "breeds", "yorkie", "hugo"]);
|
assert_eq!(route.segments(), &["dogs", "breeds", "yorkie", "hugo"]);
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ Router {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn BlogPost(cx: Scope) -> Element {
|
fn BlogPost(cx: Scope) -> Element {
|
||||||
let route = use_route(&cx);
|
let route = use_route(cx);
|
||||||
|
|
||||||
match route.segment("post").and_then(parse) {
|
match route.segment("post").and_then(parse) {
|
||||||
Some(post) => cx.render(rsx!{ div { "Post {post}" } })
|
Some(post) => cx.render(rsx!{ div { "Post {post}" } })
|
||||||
@@ -168,7 +168,7 @@ Listeners can also be attached downstream in your app with the `RouteListener` h
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn TitleCard(cx: Scope) -> Element {
|
fn TitleCard(cx: Scope) -> Element {
|
||||||
let (title, set_title) = use_state(&cx, || "First");
|
let (title, set_title) = use_state(cx, || "First");
|
||||||
|
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
h1 { "render {title}" }
|
h1 { "render {title}" }
|
||||||
|
|||||||
@@ -192,16 +192,16 @@ impl ToTokens for Element {
|
|||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone, Debug, Hash)]
|
#[derive(PartialEq, Eq, Clone, Debug, Hash)]
|
||||||
pub enum ElementAttr {
|
pub enum ElementAttr {
|
||||||
/// attribute: "valuee {}"
|
/// `attribute: "value"`
|
||||||
AttrText { name: Ident, value: IfmtInput },
|
AttrText { name: Ident, value: IfmtInput },
|
||||||
|
|
||||||
/// attribute: true,
|
/// `attribute: true`
|
||||||
AttrExpression { name: Ident, value: Expr },
|
AttrExpression { name: Ident, value: Expr },
|
||||||
|
|
||||||
/// "attribute": "value {}"
|
/// `"attribute": "value"`
|
||||||
CustomAttrText { name: LitStr, value: IfmtInput },
|
CustomAttrText { name: LitStr, value: IfmtInput },
|
||||||
|
|
||||||
/// "attribute": true,
|
/// `"attribute": true`
|
||||||
CustomAttrExpression { name: LitStr, value: Expr },
|
CustomAttrExpression { name: LitStr, value: Expr },
|
||||||
|
|
||||||
// /// onclick: move |_| {}
|
// /// onclick: move |_| {}
|
||||||
|
|||||||
@@ -199,8 +199,8 @@ impl<'a> DynamicContext<'a> {
|
|||||||
let value = value.source.as_ref().unwrap();
|
let value = value.source.as_ref().unwrap();
|
||||||
quote! {
|
quote! {
|
||||||
::dioxus::core::TemplateAttribute::Static {
|
::dioxus::core::TemplateAttribute::Static {
|
||||||
name: dioxus_elements::#el_name::#name.0,
|
name: #name,
|
||||||
namespace: dioxus_elements::#el_name::#name.1,
|
namespace: None,
|
||||||
value: #value,
|
value: #value,
|
||||||
|
|
||||||
// todo: we don't diff these so we never apply the volatile flag
|
// todo: we don't diff these so we never apply the volatile flag
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use dioxus_core::prelude::*;
|
use dioxus_core::prelude::*;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct StringCache {
|
pub struct StringCache {
|
||||||
pub segments: Vec<Segment>,
|
pub segments: Vec<Segment>,
|
||||||
pub template: Template<'static>,
|
pub template: Template<'static>,
|
||||||
|
|||||||
@@ -156,26 +156,29 @@ fn to_string_works() {
|
|||||||
_ = dom.rebuild();
|
_ = dom.rebuild();
|
||||||
|
|
||||||
let mut renderer = Renderer::new();
|
let mut renderer = Renderer::new();
|
||||||
|
|
||||||
let out = renderer.render(&dom);
|
let out = renderer.render(&dom);
|
||||||
|
|
||||||
use Segment::*;
|
for item in renderer.template_cache.iter() {
|
||||||
assert_eq!(
|
if item.1.segments.len() > 5 {
|
||||||
renderer.template_cache.iter().next().unwrap().1.segments,
|
assert_eq!(
|
||||||
vec![
|
item.1.segments,
|
||||||
PreRendered("<div class=\"asdasdasd\" class=\"asdasdasd\"".into(),),
|
vec![
|
||||||
Attr(0,),
|
PreRendered("<div class=\"asdasdasd\" class=\"asdasdasd\"".into(),),
|
||||||
PreRendered(">Hello world 1 -->".into(),),
|
Attr(0,),
|
||||||
Node(0,),
|
PreRendered(">Hello world 1 -->".into(),),
|
||||||
PreRendered("<-- Hello world 2<div>nest 1</div><div></div><div>nest 2</div>".into(),),
|
Node(0,),
|
||||||
Node(1,),
|
PreRendered(
|
||||||
Node(2,),
|
"<-- Hello world 2<div>nest 1</div><div></div><div>nest 2</div>".into(),
|
||||||
PreRendered("</div>".into(),),
|
),
|
||||||
]
|
Node(1,),
|
||||||
);
|
Node(2,),
|
||||||
|
PreRendered("</div>".into(),),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
assert_eq!(
|
use Segment::*;
|
||||||
out,
|
|
||||||
"<div class=\"asdasdasd\" class=\"asdasdasd\" id=\"id-123\">Hello world 1 --><!--#-->123<!--/#--><-- Hello world 2<div>nest 1</div><div></div><div>nest 2</div><!--#--></diiiiiiiiv><!--/#--><div><!--#-->finalize 0<!--/#--></div><div><!--#-->finalize 1<!--/#--></div><div><!--#-->finalize 2<!--/#--></div><div><!--#-->finalize 3<!--/#--></div><div><!--#-->finalize 4<!--/#--></div></div>"
|
assert_eq!(out, "<div class=\"asdasdasd\" class=\"asdasdasd\" id=\"id-123\">Hello world 1 -->123<-- Hello world 2<div>nest 1</div><div></div><div>nest 2</div></diiiiiiiiv><div>finalize 0</div><div>finalize 1</div><div>finalize 2</div><div>finalize 3</div><div>finalize 4</div></div>");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
@@ -41,7 +41,7 @@ struct BoxProps {
|
|||||||
}
|
}
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn Box(cx: Scope<BoxProps>) -> Element {
|
fn Box(cx: Scope<BoxProps>) -> Element {
|
||||||
let count = use_state(&cx, || 0);
|
let count = use_state(cx, || 0);
|
||||||
|
|
||||||
let x = cx.props.x * 2;
|
let x = cx.props.x * 2;
|
||||||
let y = cx.props.y * 2;
|
let y = cx.props.y * 2;
|
||||||
@@ -70,8 +70,8 @@ struct GridProps {
|
|||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn Grid(cx: Scope<GridProps>) -> Element {
|
fn Grid(cx: Scope<GridProps>) -> Element {
|
||||||
let size = cx.props.size;
|
let size = cx.props.size;
|
||||||
let count = use_state(&cx, || 0);
|
let count = use_state(cx, || 0);
|
||||||
let counts = use_ref(&cx, || vec![0; size * size]);
|
let counts = use_ref(cx, || vec![0; size * size]);
|
||||||
|
|
||||||
let ctx: &TuiContext = cx.consume_context().unwrap();
|
let ctx: &TuiContext = cx.consume_context().unwrap();
|
||||||
if *count.get() + 1 >= (size * size) {
|
if *count.get() + 1 >= (size * size) {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ enum Event {
|
|||||||
const MAX_EVENTS: usize = 8;
|
const MAX_EVENTS: usize = 8;
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let events = use_ref(&cx, Vec::new);
|
let events = use_ref(cx, Vec::new);
|
||||||
|
|
||||||
let events_lock = events.read();
|
let events_lock = events.read();
|
||||||
let first_index = events_lock.len().saturating_sub(MAX_EVENTS);
|
let first_index = events_lock.len().saturating_sub(MAX_EVENTS);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
let radius = use_state(&cx, || 0);
|
let radius = use_state(cx, || 0);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div {
|
||||||
|
|||||||
Loaded 100 of 113 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user