mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 06:34:20 +00:00
docs: update local examples and docs to support new syntaxes
This commit is contained in:
parent
e495b09bf1
commit
4de16c4779
118 changed files with 520 additions and 1154 deletions
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
|
@ -1,3 +1,7 @@
|
|||
{
|
||||
"rust-analyzer.cargo.allFeatures": true
|
||||
"rust-analyzer.cargo.allFeatures": true,
|
||||
"rust-analyzer.cargo.features": [
|
||||
"desktop",
|
||||
"router"
|
||||
],
|
||||
}
|
||||
|
|
19
README.md
19
README.md
|
@ -49,7 +49,7 @@
|
|||
Dioxus is a portable, performant, and ergonomic framework for building cross-platform user experiences in Rust.
|
||||
|
||||
```rust
|
||||
fn App(cx: Scope<()>) -> Element {
|
||||
fn app(cx: Scope<()>) -> Element {
|
||||
let mut count = use_state(&cx, || 0);
|
||||
|
||||
cx.render(rsx!(
|
||||
|
@ -76,23 +76,21 @@ If you know React, then you already know Dioxus.
|
|||
|
||||
<table style="width:100%" align="center">
|
||||
<tr >
|
||||
<th><a href="http://github.com/jkelleyrtp/dioxus">Web</a></th>
|
||||
<th><a href="http://github.com/jkelleyrtp/dioxus">Desktop</a></th>
|
||||
<th><a href="http://github.com/jkelleyrtp/dioxus">Mobile</a></th>
|
||||
<th><a href="http://github.com/jkelleyrtp/dioxus">State</a></th>
|
||||
<th><a href="http://github.com/jkelleyrtp/dioxus">Docs</a></th>
|
||||
<th><a href="http://github.com/jkelleyrtp/dioxus">Tools</a></th>
|
||||
<th><a href="https://dioxuslabs.com/book/">Web</a></th>
|
||||
<th><a href="https://dioxuslabs.com/book/">Desktop</a></th>
|
||||
<th><a href="https://dioxuslabs.com/book/">Mobile</a></th>
|
||||
<th><a href="https://dioxuslabs.com/book/">State</a></th>
|
||||
<th><a href="https://dioxuslabs.com/book/">Docs</a></th>
|
||||
<th><a href="https://dioxuslabs.com/book/">Tools</a></th>
|
||||
<tr>
|
||||
</table>
|
||||
|
||||
## Examples:
|
||||
|
||||
| File Navigator (Desktop) | Bluetooth scanner (Desktop) | TodoMVC (All platforms) | Widget Gallery |
|
||||
| File Navigator (Desktop) | Bluetooth scanner (Desktop) | TodoMVC (All platforms) | Tailwind (Liveview) |
|
||||
| --------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [![asd](https://github.com/DioxusLabs/file-explorer-example/raw/master/image.png)](https://github.com/DioxusLabs/file-explorer-example) | [![asd](https://github.com/DioxusLabs/file-explorer-example/raw/master/image.png)](https://github.com/DioxusLabs/file-explorer-example) | [![asd](https://github.com/DioxusLabs/todomvc/raw/master/example.png)](https://github.com/dioxusLabs/todomvc/) | [![asd](https://github.com/DioxusLabs/file-explorer-example/raw/master/image.png)](https://github.com/DioxusLabs/file-explorer-example) |
|
||||
|
||||
<!-- | ![asd](https://github.com/DioxusLabs/todomvc/blob/master/example.png) | [![asd](https://github.com/DioxusLabs/todomvc/blob/master/example.png)](https://github.com/dioxusLabs/todomvc/) | ![asd](https://sixtyfps.io/resources/printerdemo_screenshot.png) | -->
|
||||
|
||||
|
||||
See the awesome-dioxus page for a curated list of content in the Dioxus Ecosystem.
|
||||
|
||||
|
@ -169,6 +167,7 @@ Dioxus is heavily inspired by React, but we want your transition to feel like an
|
|||
| 1st class global state | ✅ | ✅ | redux/recoil/mobx on top of context |
|
||||
| Runs natively | ✅ | ❓ | runs as a portable binary w/o a runtime (Node) |
|
||||
| Subtree Memoization | ✅ | ❓ | skip diffing static element subtrees |
|
||||
| High-efficiency templates | 🛠 | ❓ | rsx! calls are translated to templates on the DOM's side |
|
||||
| Compile-time correct | ✅ | ❓ | Throw errors on invalid template layouts |
|
||||
| Heuristic Engine | ✅ | ❓ | track component memory usage to minimize future allocations |
|
||||
| Fine-grained reactivity | 👀 | ❓ | Skip diffing for fine-grain updates |
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
```rust
|
||||
fn App(cx: Context, props: &()) -> Element {
|
||||
let mut count = use_state(cx, || 0);
|
||||
let mut count = use_state(&cx, || 0);
|
||||
|
||||
cx.render(rsx!(
|
||||
h1 { "High-Five counter: {count}" }
|
||||
|
@ -53,7 +53,7 @@ Dioxus supports server-side rendering!
|
|||
For rendering statically to an `.html` file or from a WebServer, then you'll want to make sure the `ssr` feature is enabled in the `dioxus` crate and use the `dioxus::ssr` API. We don't expect the SSR API to change drastically in the future.
|
||||
|
||||
```rust
|
||||
let contents = dioxus::ssr::render_vdom(&dom, |c| c);
|
||||
let contents = dioxus::ssr::render_vdom(&dom);
|
||||
```
|
||||
|
||||
[Jump to the getting started guide for SSR.]()
|
||||
|
|
|
@ -45,7 +45,7 @@ As the UI grows in scale, our logic to keep each element in the proper state wou
|
|||
Instead, with Dioxus, we *declare* what we want our UI to look like:
|
||||
|
||||
```rust
|
||||
let mut state = use_state(cx, || "red");
|
||||
let mut state = use_state(&cx, || "red");
|
||||
|
||||
cx.render(rsx!(
|
||||
Container {
|
||||
|
|
|
@ -21,9 +21,9 @@ fn test() -> DomTree {
|
|||
}
|
||||
}
|
||||
|
||||
static TestComponent: FC<()> = |cx, props|html!{<div>"Hello world"</div>};
|
||||
static TestComponent: Component<()> = |cx, props|html!{<div>"Hello world"</div>};
|
||||
|
||||
static TestComponent: FC<()> = |cx, props|{
|
||||
static TestComponent: Component<()> = |cx, props|{
|
||||
let g = "BLAH";
|
||||
html! {
|
||||
<div> "Hello world" </div>
|
||||
|
@ -31,7 +31,7 @@ static TestComponent: FC<()> = |cx, props|{
|
|||
};
|
||||
|
||||
#[functional_component]
|
||||
static TestComponent: FC<{ name: String }> = |cx, props|html! { <div> "Hello {name}" </div> };
|
||||
static TestComponent: Component<{ name: String }> = |cx, props|html! { <div> "Hello {name}" </div> };
|
||||
```
|
||||
|
||||
## Why this behavior?
|
||||
|
|
|
@ -12,7 +12,7 @@ Your component today might look something like this:
|
|||
|
||||
```rust
|
||||
fn Comp(cx: Context<()>) -> DomTree {
|
||||
let (title, set_title) = use_state(cx, || "Title".to_string());
|
||||
let (title, set_title) = use_state(&cx, || "Title".to_string());
|
||||
cx.render(rsx!{
|
||||
input {
|
||||
value: title,
|
||||
|
@ -26,7 +26,7 @@ This component is fairly straightforward - the input updates its own value on ev
|
|||
|
||||
```rust
|
||||
fn Comp(cx: Context<()>) -> DomTree {
|
||||
let (title, set_title) = use_state(cx, || "Title".to_string());
|
||||
let (title, set_title) = use_state(&cx, || "Title".to_string());
|
||||
cx.render(rsx!{
|
||||
div {
|
||||
input {
|
||||
|
@ -96,7 +96,7 @@ Sometimes you want a signal to propagate across your app, either through far-awa
|
|||
|
||||
```rust
|
||||
const TITLE: Atom<String> = || "".to_string();
|
||||
const Provider: FC<()> = |cx, props|{
|
||||
const Provider: Component<()> = |cx, props|{
|
||||
let title = use_signal(&cx, &TITLE);
|
||||
rsx!(cx, input { value: title })
|
||||
};
|
||||
|
@ -105,7 +105,7 @@ const Provider: FC<()> = |cx, props|{
|
|||
If we use the `TITLE` atom in another component, we can cause updates to flow between components without calling render or diffing either component trees:
|
||||
|
||||
```rust
|
||||
const Receiver: FC<()> = |cx, props|{
|
||||
const Receiver: Component<()> = |cx, props|{
|
||||
let title = use_signal(&cx, &TITLE);
|
||||
log::info!("This will only be called once!");
|
||||
rsx!(cx,
|
||||
|
@ -132,7 +132,7 @@ Dioxus automatically understands how to use your signals when mixed with iterato
|
|||
|
||||
```rust
|
||||
const DICT: AtomFamily<String, String> = |_| {};
|
||||
const List: FC<()> = |cx, props|{
|
||||
const List: Component<()> = |cx, props|{
|
||||
let dict = use_signal(&cx, &DICT);
|
||||
cx.render(rsx!(
|
||||
ul {
|
||||
|
|
|
@ -124,7 +124,7 @@ fn VoteButton(cx: Context, props: &VoteButtonProps) -> Element {
|
|||
cx.render(rsx!{
|
||||
div { class: "votebutton"
|
||||
div { class: "arrow up" }
|
||||
div { class: "score", "{props.score}"}
|
||||
div { class: "score", "{cx.props.score}"}
|
||||
div { class: "arrow down" }
|
||||
}
|
||||
})
|
||||
|
@ -147,7 +147,7 @@ struct TitleCardProps<'a> {
|
|||
|
||||
fn TitleCard(cx: Context, props: &TitleCardProps) -> Element {
|
||||
cx.render(rsx!{
|
||||
h1 { "{props.title}" }
|
||||
h1 { "{cx.props.title}" }
|
||||
})
|
||||
}
|
||||
```
|
||||
|
|
|
@ -83,7 +83,7 @@ fn App(cx: Context, props: &())-> Element {
|
|||
|
||||
This syntax even enables us to write a one-line component:
|
||||
```rust
|
||||
static App: FC<()> = |cx, props| rsx!(cx, "hello world!");
|
||||
static App: Component<()> = |cx, props| rsx!(cx, "hello world!");
|
||||
```
|
||||
|
||||
Alternatively, for match statements, we can just return the builder itself and pass it into a final, single call to `cx.render`:
|
||||
|
|
|
@ -22,7 +22,7 @@ Let's say our app looks something like this:
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
dioxus::desktop::launch(App, |c| c);
|
||||
dioxus::desktop::launch(App);
|
||||
}
|
||||
|
||||
fn App((cx, props): Component<()>) -> Element {}
|
||||
|
@ -87,7 +87,7 @@ In our `main.rs`, we'll want to declare the `post` module so we can access our `
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
dioxus::desktop::launch(App, |c| c);
|
||||
dioxus::desktop::launch(App);
|
||||
}
|
||||
|
||||
mod post;
|
||||
|
@ -186,7 +186,7 @@ Ultimately, including and exporting components is governed by Rust's module syst
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
dioxus::desktop::launch(App, |c| c);
|
||||
dioxus::desktop::launch(App);
|
||||
}
|
||||
|
||||
mod post;
|
||||
|
|
|
@ -64,7 +64,7 @@ The most common hook you'll use for storing state is `use_state`. `use_state` pr
|
|||
|
||||
```rust
|
||||
fn App(cx: Context, props: &())-> Element {
|
||||
let post = use_state(cx, || {
|
||||
let post = use_state(&cx, || {
|
||||
PostData {
|
||||
id: Uuid::new_v4(),
|
||||
score: 10,
|
||||
|
@ -112,7 +112,7 @@ For example, let's say we provide a button to generate a new post. Whenever the
|
|||
|
||||
```rust
|
||||
fn App(cx: Context, props: &())-> Element {
|
||||
let post = use_state(cx, || PostData::new());
|
||||
let post = use_state(&cx, || PostData::new());
|
||||
|
||||
cx.render(rsx!{
|
||||
button {
|
||||
|
@ -135,7 +135,7 @@ We can use tasks in our components to build a tiny stopwatch that ticks every se
|
|||
```rust
|
||||
|
||||
fn App(cx: Context, props: &())-> Element {
|
||||
let mut sec_elapsed = use_state(cx, || 0);
|
||||
let mut sec_elapsed = use_state(&cx, || 0);
|
||||
|
||||
cx.spawn_task(async move {
|
||||
TimeoutFuture::from_ms(1000).await;
|
||||
|
|
|
@ -92,7 +92,7 @@ use dioxus::prelude::*;
|
|||
|
||||
|
||||
fn main() {
|
||||
dioxus::desktop::launch(App, |c| c);
|
||||
dioxus::desktop::launch(App);
|
||||
}
|
||||
|
||||
fn App(cx: Context, props: &()) -> Element {
|
||||
|
@ -118,7 +118,7 @@ This initialization code launches a Tokio runtime on a helper thread where your
|
|||
|
||||
```rust
|
||||
fn main() {
|
||||
dioxus::desktop::launch(App, |c| c);
|
||||
dioxus::desktop::launch(App);
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -135,7 +135,7 @@ fn App(cx: Context, props: &()) -> Element {
|
|||
Writing `fn App(cx: Context, props: &()) -> Element {` might become tedious. Rust will also let you write functions as static closures, but these types of Components cannot have props that borrow data.
|
||||
|
||||
```rust
|
||||
static App: FC<()> = |cx, props| cx.render(rsx!(div { "Hello, world!" }));
|
||||
static App: Component<()> = |cx, props| cx.render(rsx!(div { "Hello, world!" }));
|
||||
```
|
||||
|
||||
### What is this `Context` object?
|
||||
|
|
|
@ -72,7 +72,7 @@ fn App(cx: Context, props: &()) -> Element {
|
|||
struct ToggleProps { children: Element }
|
||||
|
||||
fn Toggle(cx: Context, props: &ToggleProps) -> Element {
|
||||
let mut toggled = use_state(cx, || false);
|
||||
let mut toggled = use_state(&cx, || false);
|
||||
cx.render(rsx!{
|
||||
div {
|
||||
{&props.children}
|
||||
|
@ -87,7 +87,7 @@ fn Toggle(cx: Context, props: &ToggleProps) -> Element {
|
|||
Controlled inputs:
|
||||
```rust
|
||||
fn App(cx: Context, props: &()) -> Element {
|
||||
let value = use_state(cx, String::new);
|
||||
let value = use_state(&cx, String::new);
|
||||
cx.render(rsx!(
|
||||
input {
|
||||
"type": "text",
|
||||
|
@ -123,13 +123,13 @@ fn App(cx: Context, props: &()) -> Element {
|
|||
|
||||
Tiny components:
|
||||
```rust
|
||||
static App: FC<()> = |cx, _| rsx!(cx, div {"hello world!"});
|
||||
static App: Component<()> = |cx, _| rsx!(cx, div {"hello world!"});
|
||||
```
|
||||
|
||||
Borrowed prop contents:
|
||||
```rust
|
||||
fn App(cx: Context, props: &()) -> Element {
|
||||
let name = use_state(cx, || String::from("example"));
|
||||
let name = use_state(&cx, || String::from("example"));
|
||||
rsx!(cx, Child { title: name.as_str() })
|
||||
}
|
||||
|
||||
|
@ -137,7 +137,7 @@ fn App(cx: Context, props: &()) -> Element {
|
|||
struct ChildProps<'a> { title: &'a str }
|
||||
|
||||
fn Child(cx: Context, props: &ChildProps) -> Element {
|
||||
rsx!(cx, "Hello {props.title}")
|
||||
rsx!(cx, "Hello {cx.props.title}")
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -8,12 +8,12 @@ use gloo_timers::future::TimeoutFuture;
|
|||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
dioxus::desktop::launch(App, |c| c);
|
||||
dioxus::desktop::launch(App);
|
||||
}
|
||||
|
||||
pub static App: Component<()> = |cx, _| {
|
||||
let count = use_state(cx, || 0);
|
||||
let mut direction = use_state(cx, || 1);
|
||||
pub static App: Component<()> = |cx| {
|
||||
let count = use_state(&cx, || 0);
|
||||
let mut direction = use_state(&cx, || 1);
|
||||
|
||||
let (async_count, dir) = (count.for_async(), *direction);
|
||||
|
||||
|
|
|
@ -17,10 +17,10 @@ and is proven to be safe with MIRI.
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
dioxus::desktop::launch(App, |c| c);
|
||||
dioxus::desktop::launch(App);
|
||||
}
|
||||
|
||||
fn App(cx: Scope, props: &()) -> Element {
|
||||
fn App(cx: Scope<()>) -> Element {
|
||||
let text: &mut Vec<String> = cx.use_hook(|_| vec![String::from("abc=def")], |f| f);
|
||||
|
||||
let first = text.get_mut(0).unwrap();
|
||||
|
@ -39,7 +39,7 @@ struct C1Props<'a> {
|
|||
text: &'a mut String,
|
||||
}
|
||||
|
||||
fn Child1(cx: Scope, props: &C1Props) -> Element {
|
||||
fn Child1<'a>(cx: Scope<'a, C1Props<'a>>) -> Element {
|
||||
let (left, right) = props.text.split_once("=").unwrap();
|
||||
|
||||
cx.render(rsx! {
|
||||
|
@ -55,7 +55,7 @@ struct C2Props<'a> {
|
|||
text: &'a str,
|
||||
}
|
||||
|
||||
fn Child2(cx: Scope, props: &C2Props) -> Element {
|
||||
fn Child2<'a>(cx: Scope<'a, C2Props<'a>>) -> Element {
|
||||
cx.render(rsx! {
|
||||
Child3 {
|
||||
text: props.text
|
||||
|
@ -68,8 +68,8 @@ struct C3Props<'a> {
|
|||
text: &'a str,
|
||||
}
|
||||
|
||||
fn Child3(cx: Scope, props: &C3Props) -> Element {
|
||||
fn Child3<'a>(cx: Scope<'a, C3Props<'a>>) -> Element {
|
||||
cx.render(rsx! {
|
||||
div { "{props.text}"}
|
||||
div { "{cx.props.text}"}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -10,13 +10,13 @@ use dioxus::prelude::*;
|
|||
use separator::Separatable;
|
||||
|
||||
fn main() {
|
||||
dioxus::desktop::launch(APP, |cfg| cfg);
|
||||
dioxus::desktop::launch(APP);
|
||||
}
|
||||
|
||||
const APP: Component<()> = |cx, _| {
|
||||
let cur_val = use_state(cx, || 0.0_f64);
|
||||
let operator = use_state(cx, || None as Option<&'static str>);
|
||||
let display_value = use_state(cx, || String::from(""));
|
||||
static APP: Component<()> = |cx| {
|
||||
let cur_val = use_state(&cx, || 0.0_f64);
|
||||
let operator = use_state(&cx, || None as Option<&'static str>);
|
||||
let display_value = use_state(&cx, || String::from(""));
|
||||
|
||||
let toggle_percent = move |_| todo!();
|
||||
let input_digit = move |num: u8| display_value.modify().push_str(num.to_string().as_str());
|
||||
|
@ -117,13 +117,13 @@ const APP: Component<()> = |cx, _| {
|
|||
struct CalculatorKeyProps<'a> {
|
||||
name: &'static str,
|
||||
onclick: &'a dyn Fn(Arc<MouseEvent>),
|
||||
children: Element,
|
||||
children: Element<'a>,
|
||||
}
|
||||
|
||||
fn CalculatorKey<'a>(cx: Scope, props: &CalculatorKeyProps) -> Element {
|
||||
fn CalculatorKey<'a>(cx: Scope<'a, CalculatorKeyProps<'a>>) -> Element {
|
||||
rsx!(cx, button {
|
||||
class: "calculator-key {props.name}"
|
||||
onclick: {props.onclick}
|
||||
class: "calculator-key {cx.props.name}"
|
||||
onclick: {cx.props.onclick}
|
||||
{&props.children}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ fn main() {
|
|||
println!("{}", dom);
|
||||
}
|
||||
|
||||
pub static EXAMPLE: FC<()> = |cx, _| {
|
||||
pub static EXAMPLE: Component<()> = |cx| {
|
||||
let list = (0..10).map(|_f| {
|
||||
rsx! {
|
||||
"{_f}"
|
||||
|
|
|
@ -5,7 +5,7 @@ fn main() {
|
|||
dom.rebuild();
|
||||
}
|
||||
|
||||
const App: FC<()> = |cx, props| {
|
||||
const App: Component<()> = |cx| {
|
||||
let id = cx.scope_id();
|
||||
// cx.submit_task(Box::pin(async move { id }));
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ struct SomeContext {
|
|||
}
|
||||
|
||||
#[allow(unused)]
|
||||
static Example: FC<()> = |cx, props| {
|
||||
static Example: Component<()> = |cx| {
|
||||
todo!()
|
||||
|
||||
// let value = cx.use_context(|c: &SomeContext| c.items.last().unwrap());
|
||||
|
|
|
@ -47,9 +47,9 @@ fn Row<'a>((cx, props): Scope<'a, RowProps>) -> Element<'a> {
|
|||
};
|
||||
cx.render(rsx! {
|
||||
tr {
|
||||
// td { class:"col-md-1", "{props.row_id}" }
|
||||
// td { class:"col-md-1", "{cx.props.row_id}" }
|
||||
// td { class:"col-md-1", onclick: move |_| { /* run onselect */ }
|
||||
// a { class: "lbl", "{props.label}" }
|
||||
// a { class: "lbl", "{cx.props.label}" }
|
||||
// }
|
||||
// td { class: "col-md-1"
|
||||
// a { class: "remove", onclick: {handler}
|
||||
|
|
|
@ -31,9 +31,9 @@ fn html_usage() {
|
|||
// let p = rsx!(div { {f} });
|
||||
}
|
||||
|
||||
static App2: FC<()> = |cx, _| cx.render(rsx!("hello world!"));
|
||||
static App2: Component<()> = |cx, _| cx.render(rsx!("hello world!"));
|
||||
|
||||
static App: FC<()> = |cx, props| {
|
||||
static App: Component<()> = |cx| {
|
||||
let name = cx.use_state(|| 0);
|
||||
|
||||
cx.render(rsx!(div {
|
||||
|
@ -71,7 +71,7 @@ struct ChildProps {
|
|||
|
||||
fn Child<'a>((cx, props): Scope<'a, ChildProps>) -> Element<'a> {
|
||||
cx.render(rsx!(div {
|
||||
// {props.children}
|
||||
// {cx.props.children}
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ impl<'a> Children<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
static Bapp: FC<()> = |cx, props| {
|
||||
static Bapp: Component<()> = |cx| {
|
||||
let name = cx.use_state(|| 0);
|
||||
|
||||
cx.render(rsx!(
|
||||
|
@ -114,7 +114,7 @@ static Bapp: FC<()> = |cx, props| {
|
|||
))
|
||||
};
|
||||
|
||||
static Match: FC<()> = |cx, props| {
|
||||
static Match: Component<()> = |cx| {
|
||||
//
|
||||
let b: Box<dyn Fn(NodeFactory) -> VNode> = Box::new(|f| todo!());
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ fn t() {
|
|||
// let a = rsx! {
|
||||
// div {
|
||||
// "asd"
|
||||
// "{props.foo}"
|
||||
// "{cx.props.foo}"
|
||||
// }
|
||||
// };
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use dioxus_core::{lazynodes::LazyNodes, prelude::*};
|
|||
|
||||
// #[async_std::main]
|
||||
fn main() {
|
||||
static App: FC<()> =
|
||||
static App: Component<()> =
|
||||
|cx, props| cx.render(Some(LazyNodes::new(move |f| f.text(format_args!("hello")))));
|
||||
|
||||
let mut dom = VirtualDom::new(App);
|
||||
|
|
|
@ -32,14 +32,14 @@ use dioxus::prelude::*;
|
|||
struct NoKeysProps {
|
||||
data: std::collections::HashMap<u32, String>,
|
||||
}
|
||||
static AntipatternNoKeys: FC<NoKeysProps> = |cx, props| {
|
||||
static AntipatternNoKeys: Component<NoKeysProps> = |cx| {
|
||||
// WRONG: Make sure to add keys!
|
||||
rsx!(cx, ul {
|
||||
{props.data.iter().map(|(k, v)| rsx!(li { "List item: {v}" }))}
|
||||
{cx.props.data.iter().map(|(k, v)| rsx!(li { "List item: {v}" }))}
|
||||
});
|
||||
// RIGHT: Like this:
|
||||
rsx!(cx, ul {
|
||||
{props.data.iter().map(|(k, v)| rsx!(li { key: "{k}", "List item: {v}" }))}
|
||||
{cx.props.data.iter().map(|(k, v)| rsx!(li { key: "{k}", "List item: {v}" }))}
|
||||
})
|
||||
};
|
||||
|
||||
|
@ -54,7 +54,7 @@ static AntipatternNoKeys: FC<NoKeysProps> = |cx, props| {
|
|||
///
|
||||
/// Only Component and Fragment nodes are susceptible to this issue. Dioxus mitigates this with components by providing
|
||||
/// an API for registering shared state without the ContextProvider pattern.
|
||||
static AntipatternNestedFragments: FC<()> = |cx, props| {
|
||||
static AntipatternNestedFragments: Component<()> = |cx| {
|
||||
// Try to avoid heavily nesting fragments
|
||||
rsx!(cx,
|
||||
Fragment {
|
||||
|
@ -82,8 +82,8 @@ static AntipatternNestedFragments: FC<()> = |cx, props| {
|
|||
/// However, calling set_state will *not* update the current version of state in the component. This should be easy to
|
||||
/// recognize from the function signature, but Dioxus will not update the "live" version of state. Calling `set_state`
|
||||
/// merely places a new value in the queue and schedules the component for a future update.
|
||||
static AntipatternRelyingOnSetState: FC<()> = |cx, props| {
|
||||
let (state, set_state) = use_state(cx, || "Hello world").classic();
|
||||
static AntipatternRelyingOnSetState: Component<()> = |cx| {
|
||||
let (state, set_state) = use_state(&cx, || "Hello world").classic();
|
||||
set_state("New state");
|
||||
// This will return false! `state` will *still* be "Hello world"
|
||||
assert!(state == &"New state");
|
||||
|
@ -99,7 +99,7 @@ static AntipatternRelyingOnSetState: FC<()> = |cx, props| {
|
|||
/// - All components must start with an uppercase character
|
||||
///
|
||||
/// i.e.: the following component will be rejected when attempted to be used in the rsx! macro
|
||||
static antipattern_component: FC<()> = |cx, props| todo!();
|
||||
static antipattern_component: Component<()> = |cx, props| todo!();
|
||||
|
||||
/// Antipattern: Misusing hooks
|
||||
/// ---------------------------
|
||||
|
@ -120,11 +120,11 @@ static antipattern_component: FC<()> = |cx, props| todo!();
|
|||
struct MisuedHooksProps {
|
||||
should_render_state: bool,
|
||||
}
|
||||
static AntipatternMisusedHooks: FC<MisuedHooksProps> = |cx, props| {
|
||||
static AntipatternMisusedHooks: Component<MisuedHooksProps> = |cx| {
|
||||
if props.should_render_state {
|
||||
// do not place a hook in the conditional!
|
||||
// prefer to move it out of the conditional
|
||||
let (state, set_state) = use_state(cx, || "hello world").classic();
|
||||
let (state, set_state) = use_state(&cx, || "hello world").classic();
|
||||
rsx!(cx, div { "{state}" })
|
||||
} else {
|
||||
rsx!(cx, div { "Not rendering state" })
|
||||
|
@ -153,7 +153,7 @@ static AntipatternMisusedHooks: FC<MisuedHooksProps> = |cx, props| {
|
|||
/// }
|
||||
/// }
|
||||
/// })
|
||||
static _example: FC<()> = |cx, props| todo!();
|
||||
static _example: Component<()> = |cx, props| todo!();
|
||||
|
||||
/// Antipattern: publishing components and hooks with all features enabled
|
||||
/// ----------------------------------------------------------------------
|
||||
|
@ -171,9 +171,9 @@ static _example: FC<()> = |cx, props| todo!();
|
|||
///
|
||||
/// This will only include the `core` dioxus crate which is relatively slim and fast to compile and avoids target-specific
|
||||
/// libraries.
|
||||
static __example: FC<()> = |cx, props| todo!();
|
||||
static __example: Component<()> = |cx, props| todo!();
|
||||
|
||||
pub static Example: FC<()> = |cx, props| {
|
||||
pub static Example: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
AntipatternNoKeys { data: std::collections::HashMap::new() }
|
||||
AntipatternNestedFragments {}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
use dioxus::prelude::*;
|
||||
|
||||
pub static Example: FC<()> = |cx, props| {
|
||||
pub static Example: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
Greeting {
|
||||
|
@ -25,10 +25,10 @@ struct GreetingProps {
|
|||
name: &'static str,
|
||||
}
|
||||
|
||||
static Greeting: FC<GreetingProps> = |cx, props| {
|
||||
static Greeting: Component<GreetingProps> = |cx| {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
h1 { "Hello, {props.name}!" }
|
||||
h1 { "Hello, {cx.props.name}!" }
|
||||
p { "Welcome to the Dioxus framework" }
|
||||
br {}
|
||||
{cx.children()}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
use dioxus::prelude::*;
|
||||
|
||||
pub static Example: FC<()> = |cx, props| {
|
||||
pub static Example: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
Banner {
|
||||
|
@ -31,7 +31,7 @@ pub static Example: FC<()> = |cx, props| {
|
|||
})
|
||||
};
|
||||
|
||||
pub static Banner: FC<()> = |cx, props| {
|
||||
pub static Banner: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
h1 { "This is a great banner!" }
|
||||
|
|
|
@ -16,10 +16,10 @@ use dioxus::prelude::*;
|
|||
pub struct MyProps {
|
||||
should_show: bool,
|
||||
}
|
||||
pub static Example0: FC<MyProps> = |cx, props| {
|
||||
pub static Example0: Component<MyProps> = |cx| {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
{props.should_show.then(|| rsx!{
|
||||
{cx.props.should_show.then(|| rsx!{
|
||||
h1 { "showing the title!" }
|
||||
})}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ pub static Example0: FC<MyProps> = |cx, props| {
|
|||
pub struct MyProps1 {
|
||||
should_show: bool,
|
||||
}
|
||||
pub static Example1: FC<MyProps1> = |cx, props| {
|
||||
pub static Example1: Component<MyProps1> = |cx| {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
// With matching
|
||||
|
@ -77,7 +77,7 @@ pub enum Color {
|
|||
pub struct MyProps2 {
|
||||
color: Color,
|
||||
}
|
||||
pub static Example2: FC<MyProps2> = |cx, props| {
|
||||
pub static Example2: Component<MyProps2> = |cx| {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
{match props.color {
|
||||
|
@ -89,9 +89,9 @@ pub static Example2: FC<MyProps2> = |cx, props| {
|
|||
})
|
||||
};
|
||||
|
||||
pub static Example: FC<()> = |cx, props| {
|
||||
let should_show = use_state(cx, || false);
|
||||
let mut color_index = use_state(cx, || 0);
|
||||
pub static Example: Component<()> = |cx| {
|
||||
let should_show = use_state(&cx, || false);
|
||||
let mut color_index = use_state(&cx, || 0);
|
||||
let color = match *color_index % 2 {
|
||||
2 => Color::Green,
|
||||
1 => Color::Yellow,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use dioxus::prelude::*;
|
||||
fn main() {}
|
||||
|
||||
pub static Example: FC<()> = |cx, props| {
|
||||
pub static Example: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
|
||||
|
@ -10,8 +10,8 @@ pub static Example: FC<()> = |cx, props| {
|
|||
};
|
||||
|
||||
// A controlled component:
|
||||
static ControlledSelect: FC<()> = |cx, props| {
|
||||
let value = use_state(cx, || String::from("Grapefruit"));
|
||||
static ControlledSelect: Component<()> = |cx| {
|
||||
let value = use_state(&cx, || String::from("Grapefruit"));
|
||||
cx.render(rsx! {
|
||||
select { value: "{value}", onchange: move |evt| value.set(evt.value()),
|
||||
option { value: "Grapefruit", "Grapefruit"}
|
||||
|
@ -23,8 +23,8 @@ static ControlledSelect: FC<()> = |cx, props| {
|
|||
};
|
||||
|
||||
// TODO - how do uncontrolled things work?
|
||||
static UncontrolledSelect: FC<()> = |cx, props| {
|
||||
let value = use_state(cx, || String::new());
|
||||
static UncontrolledSelect: Component<()> = |cx| {
|
||||
let value = use_state(&cx, || String::new());
|
||||
|
||||
cx.render(rsx! {
|
||||
select {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
use dioxus::prelude::*;
|
||||
|
||||
pub static Example: FC<()> = |cx, props| {
|
||||
pub static Example: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
custom_element {
|
||||
|
|
|
@ -5,4 +5,4 @@
|
|||
|
||||
use dioxus::prelude::*;
|
||||
|
||||
pub static Example: FC<()> = |cx, props| cx.render(rsx! { Fragment {} });
|
||||
pub static Example: Component<()> = |cx, props| cx.render(rsx! { Fragment {} });
|
||||
|
|
|
@ -23,14 +23,14 @@ fn main() {}
|
|||
/// This is one way to go about error handling (just toss things away with unwrap).
|
||||
/// However, if you get it wrong, the whole app will crash.
|
||||
/// This is pretty flimsy.
|
||||
static App: FC<()> = |cx, props| {
|
||||
static App: Component<()> = |cx| {
|
||||
let data = get_data().unwrap();
|
||||
cx.render(rsx!( div { "{data}" } ))
|
||||
};
|
||||
|
||||
/// This is a pretty verbose way of error handling
|
||||
/// However, it's still pretty good since we don't panic, just fail to render anything
|
||||
static App1: FC<()> = |cx, props| {
|
||||
static App1: Component<()> = |cx| {
|
||||
let data = match get_data() {
|
||||
Some(data) => data,
|
||||
None => return None,
|
||||
|
@ -46,7 +46,7 @@ static App1: FC<()> = |cx, props| {
|
|||
/// a user is logged in.
|
||||
///
|
||||
/// Dioxus will throw an error in the console if the None-path is ever taken.
|
||||
static App2: FC<()> = |cx, props| {
|
||||
static App2: Component<()> = |cx| {
|
||||
let data = get_data()?;
|
||||
cx.render(rsx!( div { "{data}" } ))
|
||||
};
|
||||
|
@ -54,14 +54,14 @@ static App2: FC<()> = |cx, props| {
|
|||
/// This is top-tier error handling since it displays a failure state.
|
||||
///
|
||||
/// However, the error is lacking in context.
|
||||
static App3: FC<()> = |cx, props| match get_data() {
|
||||
static App3: Component<()> = |cx, props| match get_data() {
|
||||
Some(data) => cx.render(rsx!( div { "{data}" } )),
|
||||
None => cx.render(rsx!( div { "Failed to load data :(" } )),
|
||||
};
|
||||
|
||||
/// For errors that return results, it's possible to short-circuit the match-based error handling with `.ok()` which converts
|
||||
/// a Result<T, V> into an Option<T> and lets you abort rendering by early-returning `None`
|
||||
static App4: FC<()> = |cx, props| {
|
||||
static App4: Component<()> = |cx| {
|
||||
let data = get_data_err().ok()?;
|
||||
cx.render(rsx!( div { "{data}" } ))
|
||||
};
|
||||
|
@ -69,7 +69,7 @@ static App4: FC<()> = |cx, props| {
|
|||
/// This is great error handling since it displays a failure state... with context!
|
||||
///
|
||||
/// Hopefully you'll never need to display a screen like this. It's rather bad taste
|
||||
static App5: FC<()> = |cx, props| match get_data_err() {
|
||||
static App5: Component<()> = |cx, props| match get_data_err() {
|
||||
Ok(data) => cx.render(rsx!( div { "{data}" } )),
|
||||
Err(c) => cx.render(rsx!( div { "Failed to load data: {c}" } )),
|
||||
};
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
// Returning multiple elements with rsx! or html!
|
||||
static App1: FC<()> = |cx, props| {
|
||||
static App1: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
h1 { }
|
||||
h2 { }
|
||||
|
@ -20,7 +20,7 @@ static App1: FC<()> = |cx, props| {
|
|||
};
|
||||
|
||||
// Using the Fragment component
|
||||
static App2: FC<()> = |cx, props| {
|
||||
static App2: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
Fragment {
|
||||
div {}
|
||||
|
@ -31,7 +31,7 @@ static App2: FC<()> = |cx, props| {
|
|||
};
|
||||
|
||||
// Using the `fragment` method on the NodeFactory
|
||||
static App3: FC<()> = |cx, props| {
|
||||
static App3: Component<()> = |cx| {
|
||||
cx.render(LazyNodes::new(move |fac| {
|
||||
fac.fragment_from_iter([
|
||||
fac.text(format_args!("A")),
|
||||
|
@ -42,7 +42,7 @@ static App3: FC<()> = |cx, props| {
|
|||
}))
|
||||
};
|
||||
|
||||
pub static Example: FC<()> = |cx, props| {
|
||||
pub static Example: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
App1 {}
|
||||
App2 {}
|
||||
|
|
|
@ -19,7 +19,7 @@ h1 {color: blue;}
|
|||
p {color: red;}
|
||||
"#;
|
||||
|
||||
pub static Example: FC<()> = |cx, props| {
|
||||
pub static Example: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
head { style { "{STYLE}" } }
|
||||
body {
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
use dioxus::prelude::*;
|
||||
|
||||
pub static Example: FC<()> = |cx, props| {
|
||||
pub static Example: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
head {
|
||||
style: { background_color: "powderblue" }
|
||||
|
@ -29,7 +29,7 @@ pub static Example: FC<()> = |cx, props| {
|
|||
// .... technically the rsx! macro is slightly broken at the moment and allows styles not wrapped in style {}
|
||||
// I haven't noticed any name collisions yet, and am tentatively leaving this behavior in..
|
||||
// Don't rely on it.
|
||||
static Example2: FC<()> = |cx, props| {
|
||||
static Example2: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
div { color: "red"
|
||||
"hello world!"
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
|
||||
use dioxus::prelude::*;
|
||||
|
||||
pub static Example: FC<()> = |cx, props| {
|
||||
let example_data = use_state(cx, || 0);
|
||||
pub static Example: Component<()> = |cx| {
|
||||
let example_data = use_state(&cx, || 0);
|
||||
|
||||
let v = (0..10).map(|f| {
|
||||
rsx! {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
use dioxus::prelude::*;
|
||||
|
||||
pub static Example: FC<()> = |cx, props| {
|
||||
pub static Example: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
ButtonList {}
|
||||
NonUpdatingEvents {}
|
||||
|
@ -16,8 +16,8 @@ pub static Example: FC<()> = |cx, props| {
|
|||
};
|
||||
|
||||
/// We can use `set_name` in multiple closures; the closures automatically *copy* the reference to set_name.
|
||||
static ButtonList: FC<()> = |cx, props| {
|
||||
let name = use_state(cx, || "...?");
|
||||
static ButtonList: Component<()> = |cx| {
|
||||
let name = use_state(&cx, || "...?");
|
||||
|
||||
let names = ["jack", "jill", "john", "jane"]
|
||||
.iter()
|
||||
|
@ -33,7 +33,7 @@ static ButtonList: FC<()> = |cx, props| {
|
|||
|
||||
/// This shows how listeners may be without a visible change in the display.
|
||||
/// Check the console.
|
||||
static NonUpdatingEvents: FC<()> = |cx, props| {
|
||||
static NonUpdatingEvents: Component<()> = |cx| {
|
||||
rsx!(cx, div {
|
||||
button {
|
||||
onclick: move |_| log::info!("Did not cause any updates!")
|
||||
|
@ -42,7 +42,7 @@ static NonUpdatingEvents: FC<()> = |cx, props| {
|
|||
})
|
||||
};
|
||||
|
||||
static DisablePropagation: FC<()> = |cx, props| {
|
||||
static DisablePropagation: Component<()> = |cx| {
|
||||
rsx!(cx,
|
||||
div {
|
||||
onclick: move |_| log::info!("event propagated to the div!")
|
||||
|
|
|
@ -21,7 +21,7 @@ use dioxus::prelude::*;
|
|||
|
||||
// By default, components with no props are always memoized.
|
||||
// A props of () is considered empty.
|
||||
pub static Example: FC<()> = |cx, props| {
|
||||
pub static Example: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
div { "100% memoized!" }
|
||||
})
|
||||
|
@ -35,9 +35,9 @@ pub struct MyProps1 {
|
|||
name: String,
|
||||
}
|
||||
|
||||
pub static Example1: FC<MyProps1> = |cx, props| {
|
||||
pub static Example1: Component<MyProps1> = |cx| {
|
||||
cx.render(rsx! {
|
||||
div { "100% memoized! {props.name}" }
|
||||
div { "100% memoized! {cx.props.name}" }
|
||||
})
|
||||
};
|
||||
|
||||
|
@ -49,9 +49,9 @@ pub struct MyProps2 {
|
|||
name: std::rc::Rc<str>,
|
||||
}
|
||||
|
||||
pub static Example2: FC<MyProps2> = |cx, props| {
|
||||
pub static Example2: Component<MyProps2> = |cx| {
|
||||
cx.render(rsx! {
|
||||
div { "100% memoized! {props.name}" }
|
||||
div { "100% memoized! {cx.props.name}" }
|
||||
})
|
||||
};
|
||||
|
||||
|
@ -61,11 +61,11 @@ pub struct MyProps3<'a> {
|
|||
name: &'a str,
|
||||
}
|
||||
// We need to manually specify a lifetime that ensures props and scope (the component's state) share the same lifetime.
|
||||
// Using the `pub static Example: FC<()>` pattern _will_ specify a lifetime, but that lifetime will be static which might
|
||||
// Using the `pub static Example: Component<()>` pattern _will_ specify a lifetime, but that lifetime will be static which might
|
||||
// not exactly be what you want
|
||||
fn Example3<'a>(cx: Context<'a>, props: &'a MyProps3) -> DomTree<'a> {
|
||||
cx.render(rsx! {
|
||||
div { "Not memoized! {props.name}" }
|
||||
div { "Not memoized! {cx.props.name}" }
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use dioxus::prelude::*;
|
||||
fn main() {}
|
||||
|
||||
pub static Example: FC<()> = |cx, props| {
|
||||
pub static Example: Component<()> = |cx| {
|
||||
let p = 10;
|
||||
|
||||
cx.render(rsx! {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use dioxus::prelude::*;
|
||||
fn main() {}
|
||||
|
||||
pub static Example: FC<()> = |cx, props| {
|
||||
pub static Example: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
use dioxus::prelude::*;
|
||||
|
||||
pub static Example: FC<()> = |cx, props| {
|
||||
pub static Example: Component<()> = |cx| {
|
||||
let props = MyProps {
|
||||
count: 0,
|
||||
live: true,
|
||||
|
@ -27,7 +27,7 @@ pub struct MyProps {
|
|||
name: &'static str,
|
||||
}
|
||||
|
||||
pub static Example1: FC<MyProps> = |cx, MyProps { count, live, name }| {
|
||||
pub static Example1: Component<MyProps> = |cx, MyProps { count, live, name }| {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
h1 { "Hello, {name}"}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use dioxus::prelude::*;
|
||||
fn main() {}
|
||||
|
||||
pub static Example: FC<()> = |cx, props| {
|
||||
pub static Example: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ struct DogApi {
|
|||
}
|
||||
const ENDPOINT: &str = "https://dog.ceo/api/breeds/image/random";
|
||||
|
||||
pub static Example: FC<()> = |cx, props| {
|
||||
pub static Example: Component<()> = |cx| {
|
||||
let doggo = use_suspense(
|
||||
cx,
|
||||
|| surf::get(ENDPOINT).recv_json::<DogApi>(),
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
|
||||
use dioxus::prelude::*;
|
||||
|
||||
pub static Example: FC<()> = |cx, props| {
|
||||
let count = use_state(cx, || 0);
|
||||
let mut direction = use_state(cx, || 1);
|
||||
pub static Example: Component<()> = |cx| {
|
||||
let count = use_state(&cx, || 0);
|
||||
let mut direction = use_state(&cx, || 1);
|
||||
|
||||
// Tasks are 'static, so we need to copy relevant items in
|
||||
let (async_count, dir) = (count.for_async(), *direction);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
pub static Example: FC<()> = |cx, props| {
|
||||
pub static Example: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use dioxus::prelude::*;
|
||||
use dioxus::ssr;
|
||||
|
||||
pub static Example: FC<()> = |cx, props| {
|
||||
let as_string = use_state(cx, || {
|
||||
pub static Example: Component<()> = |cx| {
|
||||
let as_string = use_state(&cx, || {
|
||||
// Currently, SSR is only supported for whole VirtualDOMs
|
||||
// This is an easy/low hanging fruit to improve upon
|
||||
let mut dom = VirtualDom::new(SomeApp);
|
||||
dom.rebuild();
|
||||
ssr::render_vdom(&dom, |c| c)
|
||||
ssr::render_vdom(&dom)
|
||||
});
|
||||
|
||||
cx.render(rsx! {
|
||||
|
@ -15,7 +15,7 @@ pub static Example: FC<()> = |cx, props| {
|
|||
})
|
||||
};
|
||||
|
||||
static SomeApp: FC<()> = |cx, props| {
|
||||
static SomeApp: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
div { style: {background_color: "blue"}
|
||||
h1 {"Some amazing app or component"}
|
||||
|
|
|
@ -22,14 +22,14 @@
|
|||
//! the coroutine was initiated. `use_state` always returns the same setter, so you don't need to worry about
|
||||
|
||||
fn main() {
|
||||
dioxus::desktop::launch(App, |c| c);
|
||||
dioxus::desktop::launch(App);
|
||||
}
|
||||
|
||||
use dioxus::prelude::*;
|
||||
|
||||
static App: Component<()> = |cx, props| {
|
||||
let p1 = use_state(cx, || 0);
|
||||
let p2 = use_state(cx, || 0);
|
||||
static App: Component<()> = |cx| {
|
||||
let p1 = use_state(&cx, || 0);
|
||||
let p2 = use_state(&cx, || 0);
|
||||
|
||||
let (mut p1_async, mut p2_async) = (p1.for_async(), p2.for_async());
|
||||
let (p1_handle, _) = use_coroutine(cx, || async move {
|
||||
|
|
|
@ -4,7 +4,7 @@ Tiny CRM: A port of the Yew CRM example to Dioxus.
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
dioxus::web::launch(App, |c| c);
|
||||
dioxus::web::launch(App);
|
||||
}
|
||||
enum Scene {
|
||||
ClientsList,
|
||||
|
@ -19,13 +19,13 @@ pub struct Client {
|
|||
pub description: String,
|
||||
}
|
||||
|
||||
static App: Component<()> = |cx, _| {
|
||||
let mut clients = use_ref(cx, || vec![] as Vec<Client>);
|
||||
let mut scene = use_state(cx, || Scene::ClientsList);
|
||||
static App: Component<()> = |cx| {
|
||||
let mut clients = use_ref(&cx, || vec![] as Vec<Client>);
|
||||
let mut scene = use_state(&cx, || Scene::ClientsList);
|
||||
|
||||
let mut firstname = use_state(cx, || String::new());
|
||||
let mut lastname = use_state(cx, || String::new());
|
||||
let mut description = use_state(cx, || String::new());
|
||||
let mut firstname = use_state(&cx, || String::new());
|
||||
let mut lastname = use_state(&cx, || String::new());
|
||||
let mut description = use_state(&cx, || String::new());
|
||||
|
||||
let scene = match *scene {
|
||||
Scene::ClientsList => {
|
||||
|
|
|
@ -5,7 +5,7 @@ use dioxus_hooks::*;
|
|||
use dioxus_html as dioxus_elements;
|
||||
|
||||
fn main() {
|
||||
dioxus_desktop::launch(App, |c| c)
|
||||
dioxus_desktop::launch(App)
|
||||
}
|
||||
|
||||
enum Scene {
|
||||
|
@ -21,13 +21,13 @@ pub struct Client {
|
|||
pub description: String,
|
||||
}
|
||||
|
||||
static App: FC<()> = |cx, _| {
|
||||
let mut scene = use_state(cx, || Scene::ClientsList);
|
||||
let clients = use_ref(cx, || vec![] as Vec<Client>);
|
||||
static App: Component<()> = |cx| {
|
||||
let mut scene = use_state(&cx, || Scene::ClientsList);
|
||||
let clients = use_ref(&cx, || vec![] as Vec<Client>);
|
||||
|
||||
let mut firstname = use_state(cx, String::new);
|
||||
let mut lastname = use_state(cx, String::new);
|
||||
let mut description = use_state(cx, String::new);
|
||||
let mut firstname = use_state(&cx, String::new);
|
||||
let mut lastname = use_state(&cx, String::new);
|
||||
let mut description = use_state(&cx, String::new);
|
||||
|
||||
let scene = match scene.get() {
|
||||
Scene::ClientsList => {
|
||||
|
|
|
@ -5,10 +5,10 @@ use dioxus_core_macro::*;
|
|||
use dioxus_html as dioxus_elements;
|
||||
|
||||
fn main() {
|
||||
dioxus_desktop::launch(App, |c| c);
|
||||
dioxus_desktop::launch(App);
|
||||
}
|
||||
|
||||
static App: FC<()> = |cx, props| {
|
||||
static App: Component<()> = |cx| {
|
||||
cx.render(rsx!(
|
||||
div {
|
||||
"hello world!"
|
||||
|
|
|
@ -14,7 +14,7 @@ fn main() {
|
|||
SimpleLogger::new().init().unwrap();
|
||||
}
|
||||
|
||||
dioxus_desktop::launch(App, |c| c)
|
||||
dioxus_desktop::launch(App)
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
|
@ -32,14 +32,14 @@ pub struct TodoItem {
|
|||
}
|
||||
pub type Todos = HashMap<u32, TodoItem>;
|
||||
|
||||
pub static App: FC<()> = |cx, _| {
|
||||
pub static App: Component<()> = |cx| {
|
||||
// Share our TodoList to the todos themselves
|
||||
use_provide_state(cx, Todos::new);
|
||||
|
||||
// Save state for the draft, filter
|
||||
let draft = use_state(cx, || "".to_string());
|
||||
let filter = use_state(cx, || FilterState::All);
|
||||
let mut todo_id = use_state(cx, || 0);
|
||||
let draft = use_state(&cx, || "".to_string());
|
||||
let filter = use_state(&cx, || FilterState::All);
|
||||
let mut todo_id = use_state(&cx, || 0);
|
||||
|
||||
// Consume the todos
|
||||
let todos = use_shared_state::<Todos>(cx)?;
|
||||
|
@ -142,7 +142,7 @@ pub fn TodoEntry((cx, props): Scope<TodoEntryProps>) -> Element {
|
|||
let _todos = todos.read();
|
||||
let todo = _todos.get(&props.id)?;
|
||||
|
||||
let is_editing = use_state(cx, || false);
|
||||
let is_editing = use_state(&cx, || false);
|
||||
let completed = if todo.checked { "completed" } else { "" };
|
||||
|
||||
cx.render(rsx!{
|
||||
|
|
|
@ -9,7 +9,7 @@ use dioxus::prelude::*;
|
|||
|
||||
fn main() {
|
||||
simple_logger::init_with_level(log::Level::Debug);
|
||||
dioxus::desktop::launch(App, |c| {
|
||||
dioxus::desktop::launch_cfg(App, |c| {
|
||||
c.with_window(|w| {
|
||||
w.with_resizable(true).with_inner_size(
|
||||
dioxus::desktop::wry::application::dpi::LogicalSize::new(400.0, 800.0),
|
||||
|
@ -18,8 +18,8 @@ fn main() {
|
|||
});
|
||||
}
|
||||
|
||||
static App: Component<()> = |cx, props| {
|
||||
let file_manager = use_ref(cx, || Files::new());
|
||||
static App: Component<()> = |cx| {
|
||||
let file_manager = use_ref(&cx, Files::new);
|
||||
let files = file_manager.read();
|
||||
|
||||
let file_list = files.path_names.iter().enumerate().map(|(dir_id, path)| {
|
||||
|
@ -39,13 +39,15 @@ static App: Component<()> = |cx, props| {
|
|||
|
||||
let current_dir = files.current();
|
||||
|
||||
rsx!(cx, div {
|
||||
h1 {"Files: "}
|
||||
h3 {"Cur dir: {current_dir}"}
|
||||
button { "go up", onclick: move |_| file_manager.write().go_up() }
|
||||
ol { {file_list} }
|
||||
{err_disp}
|
||||
})
|
||||
cx.render(rsx!(
|
||||
div {
|
||||
h1 {"Files: "}
|
||||
h3 {"Cur dir: {current_dir}"}
|
||||
button { "go up", onclick: move |_| file_manager.write().go_up() }
|
||||
ol { {file_list} }
|
||||
{err_disp}
|
||||
}
|
||||
))
|
||||
};
|
||||
|
||||
struct Files {
|
||||
|
|
|
@ -2,8 +2,8 @@ use dioxus::prelude::*;
|
|||
use rand::prelude::*;
|
||||
|
||||
fn main() {
|
||||
dioxus::web::launch(App, |c| c);
|
||||
// dioxus::desktop::launch(App, |c| c);
|
||||
dioxus::web::launch(App);
|
||||
// dioxus::desktop::launch(App);
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
|
@ -30,9 +30,9 @@ impl Label {
|
|||
}
|
||||
}
|
||||
|
||||
static App: Component<()> = |cx, _props| {
|
||||
let mut items = use_ref(cx, || vec![]);
|
||||
let mut selected = use_state(cx, || None);
|
||||
static App: Component<()> = |cx| {
|
||||
let mut items = use_ref(&cx, || vec![]);
|
||||
let mut selected = use_state(&cx, || None);
|
||||
|
||||
cx.render(rsx! {
|
||||
div { class: "container"
|
||||
|
@ -95,10 +95,10 @@ struct ActionButtonProps<'a> {
|
|||
onclick: &'a dyn Fn(),
|
||||
}
|
||||
|
||||
fn ActionButton(cx: Scope, props: &ActionButtonProps) -> Element {
|
||||
fn ActionButton<'a>(cx: Scope<'a, ActionButtonProps<'a>>) -> Element {
|
||||
rsx!(cx, div { class: "col-sm-6 smallpad"
|
||||
button { class:"btn btn-primary btn-block", r#type: "button", id: "{props.id}", onclick: move |_| (props.onclick)(),
|
||||
"{props.name}"
|
||||
button { class:"btn btn-primary btn-block", r#type: "button", id: "{cx.props.id}", onclick: move |_| (props.onclick)(),
|
||||
"{cx.props.name}"
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -149,9 +149,9 @@ static NOUNS: &[&str] = &[
|
|||
|
||||
// fn Row(cx: Context, props: &RowProps) -> Element {
|
||||
// rsx!(cx, tr {
|
||||
// td { class:"col-md-1", "{props.row_id}" }
|
||||
// td { class:"col-md-1", "{cx.props.row_id}" }
|
||||
// td { class:"col-md-1", onclick: move |_| { /* run onselect */ }
|
||||
// a { class: "lbl", {props.label.labels} }
|
||||
// a { class: "lbl", {cx.props.label.labels} }
|
||||
// }
|
||||
// td { class: "col-md-1"
|
||||
// a { class: "remove", onclick: move |_| {/* remove */}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
dioxus::desktop::launch(App, |c| c);
|
||||
dioxus::desktop::launch(App);
|
||||
}
|
||||
|
||||
fn App((cx, props): ScopeState<()>) -> Element {
|
||||
|
|
|
@ -19,8 +19,8 @@ fn main() {
|
|||
dioxus::desktop::launch(App, |c| c.with_prerendered(content));
|
||||
}
|
||||
|
||||
static App: Component<()> = |cx, props| {
|
||||
let mut val = use_state(cx, || 0);
|
||||
static App: Component<()> = |cx| {
|
||||
let mut val = use_state(&cx, || 0);
|
||||
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
|
|
|
@ -16,13 +16,13 @@
|
|||
//! RefMuts at the same time.
|
||||
|
||||
use dioxus::desktop::wry::application::dpi::LogicalSize;
|
||||
use dioxus::events::{on::*, KeyCode};
|
||||
use dioxus::events::*;
|
||||
use dioxus::prelude::*;
|
||||
|
||||
const STYLE: &str = include_str!("./assets/calculator.css");
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
dioxus::desktop::launch(App, |cfg| {
|
||||
dioxus::desktop::launch_cfg(App, |cfg| {
|
||||
cfg.with_window(|w| {
|
||||
w.with_title("Calculator Demo")
|
||||
.with_resizable(false)
|
||||
|
@ -31,8 +31,8 @@ fn main() {
|
|||
});
|
||||
}
|
||||
|
||||
static App: Component<()> = |cx, props| {
|
||||
let state = use_ref(cx, || Calculator::new());
|
||||
static App: Component<()> = |cx| {
|
||||
let state = use_ref(&cx, || Calculator::new());
|
||||
|
||||
let clear_display = state.read().display_value.eq("0");
|
||||
let clear_text = if clear_display { "C" } else { "AC" };
|
||||
|
@ -80,8 +80,8 @@ struct CalculatorKeyProps<'a> {
|
|||
fn CalculatorKey<'a>((cx, props): ScopeState<'a, CalculatorKeyProps<'a>>) -> Element<'a> {
|
||||
cx.render(rsx! {
|
||||
button {
|
||||
class: "calculator-key {props.name}"
|
||||
onclick: {props.onclick}
|
||||
class: "calculator-key {cx.props.name}"
|
||||
onclick: {cx.props.onclick}
|
||||
{&props.children}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
use dioxus::prelude::*;
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
dioxus::desktop::launch(App, |c| c);
|
||||
dioxus::desktop::launch(App);
|
||||
}
|
||||
|
||||
pub static App: Component<()> = |cx, _| {
|
||||
let state = use_state(cx, PlayerState::new);
|
||||
pub static App: Component<()> = |cx| {
|
||||
let state = use_state(&cx, PlayerState::new);
|
||||
|
||||
let is_playing = state.is_playing();
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
|
||||
use dioxus::prelude::*;
|
||||
fn main() {
|
||||
dioxus::desktop::launch(App, |c| c);
|
||||
dioxus::desktop::launch(App);
|
||||
}
|
||||
|
||||
static App: Component<()> = |cx, props| {
|
||||
let mut count = use_state(cx, || 0);
|
||||
static App: Component<()> = |cx| {
|
||||
let mut count = use_state(&cx, || 0);
|
||||
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
|
|
|
@ -23,7 +23,7 @@ pub enum Route {
|
|||
NotFound,
|
||||
}
|
||||
|
||||
static App: Component<()> = |cx, props| {
|
||||
static App: Component<()> = |cx| {
|
||||
let route = use_router(cx, Route::parse)?;
|
||||
|
||||
cx.render(rsx! {
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
//! - Allow top-level fragments
|
||||
//!
|
||||
fn main() {
|
||||
dioxus::desktop::launch(Example, |c| c);
|
||||
dioxus::desktop::launch(Example);
|
||||
}
|
||||
|
||||
/// When trying to return "nothing" to Dioxus, you'll need to specify the type parameter or Rust will be sad.
|
||||
|
@ -49,7 +49,7 @@ const NONE_ELEMENT: Option<()> = None;
|
|||
use baller::Baller;
|
||||
use dioxus::prelude::*;
|
||||
|
||||
pub static Example: Component<()> = |cx, props| {
|
||||
pub static Example: Component<()> = |cx| {
|
||||
let formatting = "formatting!";
|
||||
let formatting_tuple = ("a", "b");
|
||||
let lazy_fmt = format_args!("lazily formatted text");
|
||||
|
|
|
@ -5,11 +5,11 @@ use dioxus::ssr;
|
|||
|
||||
fn main() {
|
||||
let mut vdom = VirtualDom::new(App);
|
||||
// vdom.rebuild_in_place().expect("Rebuilding failed");
|
||||
println!("{}", ssr::render_vdom(&vdom, |c| c));
|
||||
vdom.rebuild_in_place().expect("Rebuilding failed");
|
||||
println!("{}", ssr::render_vdom(&vdom));
|
||||
}
|
||||
|
||||
static App: Component<()> = |cx, props| {
|
||||
static App: Component<()> = |cx| {
|
||||
cx.render(rsx!(
|
||||
div {
|
||||
h1 { "Title" }
|
||||
|
@ -21,6 +21,6 @@ static App: Component<()> = |cx, props| {
|
|||
struct MyProps<'a> {
|
||||
text: &'a str,
|
||||
}
|
||||
fn App2(cx: Scope, props: &MyProps) -> Element {
|
||||
fn App2<'a>(cx: Scope<'a, MyProps<'a>>) -> Element {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ fn main() {
|
|||
)
|
||||
}
|
||||
|
||||
pub static App: FC<()> = |cx, props| {
|
||||
pub static App: Component<()> = |cx| {
|
||||
cx.render(rsx!(
|
||||
div {
|
||||
class: "overflow-hidden"
|
||||
|
|
|
@ -26,7 +26,7 @@ fn main() {}
|
|||
// dom.rebuild();
|
||||
|
||||
// Ok(Response::builder(200)
|
||||
// .body(format!("{}", dioxus_ssr::render_vdom(&dom, |c| c)))
|
||||
// .body(format!("{}", dioxus_ssr::render_vdom(&dom)))
|
||||
// .content_type(tide::http::mime::HTML)
|
||||
// .build())
|
||||
// });
|
||||
|
@ -42,8 +42,8 @@ fn main() {}
|
|||
// initial_name: String,
|
||||
// }
|
||||
|
||||
// static Example: FC<ExampleProps> = |cx, props| {
|
||||
// let dispaly_name = use_state(cx, move || props.initial_name.clone());
|
||||
// static Example: Component<ExampleProps> = |cx| {
|
||||
// let dispaly_name = use_state(&cx, move || props.initial_name.clone());
|
||||
|
||||
// cx.render(rsx! {
|
||||
// div { class: "py-12 px-4 text-center w-full max-w-2xl mx-auto",
|
||||
|
|
|
@ -24,7 +24,7 @@ fn main() {
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
pub static App: FC<()> = |cx, props| {
|
||||
pub static App: Component<()> = |cx| {
|
||||
cx.render(rsx!(
|
||||
div { class: "overflow-hidden"
|
||||
link { href:"https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel:"stylesheet" }
|
||||
|
@ -39,7 +39,7 @@ pub static App: FC<()> = |cx, props| {
|
|||
))
|
||||
};
|
||||
|
||||
pub static Header: FC<()> = |cx, props| {
|
||||
pub static Header: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
header { class: "text-gray-400 bg-gray-900 body-font"
|
||||
|
@ -65,7 +65,7 @@ pub static Header: FC<()> = |cx, props| {
|
|||
})
|
||||
};
|
||||
|
||||
pub static Hero: FC<()> = |cx, props| {
|
||||
pub static Hero: Component<()> = |cx| {
|
||||
//
|
||||
cx.render(rsx! {
|
||||
section{ class: "text-gray-400 bg-gray-900 body-font"
|
||||
|
@ -103,7 +103,7 @@ pub static Hero: FC<()> = |cx, props| {
|
|||
}
|
||||
})
|
||||
};
|
||||
pub static Entry: FC<()> = |cx, props| {
|
||||
pub static Entry: Component<()> = |cx| {
|
||||
//
|
||||
cx.render(rsx! {
|
||||
section{ class: "text-gray-400 bg-gray-900 body-font"
|
||||
|
@ -116,7 +116,7 @@ pub static Entry: FC<()> = |cx, props| {
|
|||
})
|
||||
};
|
||||
|
||||
pub static StacksIcon: FC<()> = |cx, props| {
|
||||
pub static StacksIcon: Component<()> = |cx| {
|
||||
cx.render(rsx!(
|
||||
svg {
|
||||
xmlns: "http://www.w3.org/2000/svg"
|
||||
|
@ -131,7 +131,7 @@ pub static StacksIcon: FC<()> = |cx, props| {
|
|||
}
|
||||
))
|
||||
};
|
||||
pub static RightArrowIcon: FC<()> = |cx, props| {
|
||||
pub static RightArrowIcon: Component<()> = |cx| {
|
||||
cx.render(rsx!(
|
||||
svg {
|
||||
fill: "none"
|
||||
|
|
|
@ -14,7 +14,7 @@ fn main() {
|
|||
|
||||
const STYLE: &str = "body {overflow:hidden;}";
|
||||
|
||||
pub static App: Component<()> = |cx, props| {
|
||||
pub static App: Component<()> = |cx| {
|
||||
cx.render(rsx!(
|
||||
div { class: "overflow-hidden"
|
||||
style { "{STYLE}" }
|
||||
|
@ -30,7 +30,7 @@ pub static App: Component<()> = |cx, props| {
|
|||
))
|
||||
};
|
||||
|
||||
pub static Header: Component<()> = |cx, props| {
|
||||
pub static Header: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
header { class: "text-gray-400 bg-gray-900 body-font"
|
||||
|
@ -56,7 +56,7 @@ pub static Header: Component<()> = |cx, props| {
|
|||
})
|
||||
};
|
||||
|
||||
pub static Hero: Component<()> = |cx, props| {
|
||||
pub static Hero: Component<()> = |cx| {
|
||||
//
|
||||
cx.render(rsx! {
|
||||
section{ class: "text-gray-400 bg-gray-900 body-font"
|
||||
|
@ -94,7 +94,7 @@ pub static Hero: Component<()> = |cx, props| {
|
|||
}
|
||||
})
|
||||
};
|
||||
pub static Entry: Component<()> = |cx, props| {
|
||||
pub static Entry: Component<()> = |cx| {
|
||||
//
|
||||
cx.render(rsx! {
|
||||
section{ class: "text-gray-400 bg-gray-900 body-font"
|
||||
|
@ -107,7 +107,7 @@ pub static Entry: Component<()> = |cx, props| {
|
|||
})
|
||||
};
|
||||
|
||||
pub static StacksIcon: Component<()> = |cx, props| {
|
||||
pub static StacksIcon: Component<()> = |cx| {
|
||||
cx.render(rsx!(
|
||||
svg {
|
||||
// xmlns: "http://www.w3.org/2000/svg"
|
||||
|
@ -122,7 +122,7 @@ pub static StacksIcon: Component<()> = |cx, props| {
|
|||
}
|
||||
))
|
||||
};
|
||||
pub static RightArrowIcon: Component<()> = |cx, props| {
|
||||
pub static RightArrowIcon: Component<()> = |cx| {
|
||||
cx.render(rsx!(
|
||||
svg {
|
||||
fill: "none"
|
||||
|
|
|
@ -6,11 +6,11 @@ use std::time::Duration;
|
|||
|
||||
use dioxus::prelude::*;
|
||||
fn main() {
|
||||
dioxus::desktop::launch(App, |c| c);
|
||||
dioxus::desktop::launch(App);
|
||||
}
|
||||
|
||||
static App: Component<()> = |cx, props| {
|
||||
let mut count = use_state(cx, || 0);
|
||||
static App: Component<()> = |cx| {
|
||||
let mut count = use_state(&cx, || 0);
|
||||
|
||||
cx.push_task(async move {
|
||||
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||
|
|
|
@ -4,7 +4,7 @@ use im_rc::HashMap;
|
|||
use std::rc::Rc;
|
||||
|
||||
fn main() {
|
||||
dioxus::desktop::launch(App, |c| c);
|
||||
dioxus::desktop::launch(App);
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
|
@ -22,10 +22,10 @@ pub struct TodoItem {
|
|||
}
|
||||
|
||||
const STYLE: &str = include_str!("./assets/todomvc.css");
|
||||
const App: Component<()> = |cx, props| {
|
||||
let mut draft = use_state(cx, || "".to_string());
|
||||
let mut todos = use_state(cx, || HashMap::<u32, Rc<TodoItem>>::new());
|
||||
let mut filter = use_state(cx, || FilterState::All);
|
||||
const App: Component<()> = |cx| {
|
||||
let mut draft = use_state(&cx, || "".to_string());
|
||||
let mut todos = use_state(&cx, || HashMap::<u32, Rc<TodoItem>>::new());
|
||||
let mut filter = use_state(&cx, || FilterState::All);
|
||||
|
||||
let todolist = todos
|
||||
.iter()
|
||||
|
@ -85,9 +85,9 @@ pub struct TodoEntryProps {
|
|||
todo: Rc<TodoItem>,
|
||||
}
|
||||
|
||||
pub fn TodoEntry(cx: Scope, props: &TodoEntryProps) -> Element {
|
||||
let mut is_editing = use_state(cx, || false);
|
||||
let mut contents = use_state(cx, || String::from(""));
|
||||
pub fn TodoEntry(cx: Scope<TodoEntryProps>) -> Element {
|
||||
let mut is_editing = use_state(&cx, || false);
|
||||
let mut contents = use_state(&cx, || String::from(""));
|
||||
let todo = &props.todo;
|
||||
|
||||
rsx!(cx, li {
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
dioxus::desktop::launch(App, |c| c);
|
||||
dioxus::desktop::launch(App);
|
||||
}
|
||||
|
||||
const ENDPOINT: &str = "https://api.openweathermap.org/data/2.5/weather";
|
||||
|
||||
static App: Component<()> = |cx, props| {
|
||||
static App: Component<()> = |cx| {
|
||||
//
|
||||
let body = use_suspense(
|
||||
cx,
|
||||
|
@ -40,7 +40,7 @@ static App: Component<()> = |cx, props| {
|
|||
#[derive(PartialEq, Props)]
|
||||
struct WeatherProps {}
|
||||
|
||||
static WeatherDisplay: Component<WeatherProps> = |cx, props| {
|
||||
static WeatherDisplay: Component<WeatherProps> = |cx| {
|
||||
//
|
||||
cx.render(rsx!(
|
||||
div { class: "flex items-center justify-center flex-col"
|
||||
|
|
|
@ -8,7 +8,7 @@ use dioxus_html as dioxus_elements;
|
|||
fn main() {
|
||||
console_error_panic_hook::set_once();
|
||||
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
||||
dioxus_web::launch(APP, |c| c)
|
||||
dioxus_web::launch(APP)
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
|
@ -16,8 +16,8 @@ struct DogApi {
|
|||
message: String,
|
||||
}
|
||||
|
||||
static APP: FC<()> = |(cx, _props)| {
|
||||
let state = use_state(cx, || 0);
|
||||
static APP: Component<()> = |(cx, _props)| {
|
||||
let state = use_state(&cx, || 0);
|
||||
|
||||
const ENDPOINT: &str = "https://dog.ceo/api/breeds/image/random/";
|
||||
let doggo = use_suspense(
|
||||
|
|
|
@ -11,13 +11,13 @@ fn main() {
|
|||
console_error_panic_hook::set_once();
|
||||
|
||||
// Run the app
|
||||
dioxus_web::launch(APP, |c| c)
|
||||
dioxus_web::launch(APP)
|
||||
}
|
||||
|
||||
static APP: FC<()> = |cx, _| {
|
||||
let mut count = use_state(cx, || 3);
|
||||
let content = use_state(cx, || String::from("h1"));
|
||||
let text_content = use_state(cx, || String::from("Hello, world!"));
|
||||
static APP: Component<()> = |cx| {
|
||||
let mut count = use_state(&cx, || 3);
|
||||
let content = use_state(&cx, || String::from("h1"));
|
||||
let text_content = use_state(&cx, || String::from("Hello, world!"));
|
||||
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
|
@ -86,4 +86,4 @@ fn render_list(cx: Context, count: usize) -> Element {
|
|||
rsx!(cx, ul { {items} })
|
||||
}
|
||||
|
||||
static CHILD: FC<()> = |cx, _| rsx!(cx, div {"hello child"});
|
||||
static CHILD: Component<()> = |cx, _| rsx!(cx, div {"hello child"});
|
||||
|
|
|
@ -21,11 +21,11 @@ fn main() {
|
|||
console_error_panic_hook::set_once();
|
||||
|
||||
// Run the app
|
||||
dioxus_web::launch(App, |c| c)
|
||||
dioxus_web::launch(App)
|
||||
}
|
||||
|
||||
static App: FC<()> = |cx, props| {
|
||||
let mut state = use_state(cx, || 0);
|
||||
static App: Component<()> = |cx| {
|
||||
let mut state = use_state(&cx, || 0);
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
style: {
|
||||
|
|
|
@ -18,12 +18,12 @@ use dioxus_html as dioxus_elements;
|
|||
// #[cfg]
|
||||
fn main() {
|
||||
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
||||
dioxus_web::launch(App, |c| c);
|
||||
dioxus_web::launch(App);
|
||||
// env_logger::init();
|
||||
// dioxus::web::launch(App, |c| c);
|
||||
// dioxus::web::launch(App);
|
||||
}
|
||||
|
||||
static App: FC<()> = |cx, props| {
|
||||
static App: Component<()> = |cx| {
|
||||
dbg!("rednering parent");
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
|
@ -40,8 +40,8 @@ static App: FC<()> = |cx, props| {
|
|||
})
|
||||
};
|
||||
|
||||
static But: FC<()> = |cx, props| {
|
||||
let mut count = use_state(cx, || 0);
|
||||
static But: Component<()> = |cx| {
|
||||
let mut count = use_state(&cx, || 0);
|
||||
|
||||
// let d = Dropper { name: "asd" };
|
||||
// let handler = move |_| {
|
||||
|
|
|
@ -12,7 +12,7 @@ fn main() {
|
|||
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
dioxus_web::launch(App, |c| c)
|
||||
dioxus_web::launch(App)
|
||||
}
|
||||
|
||||
enum Scene {
|
||||
|
@ -28,13 +28,13 @@ pub struct Client {
|
|||
pub description: String,
|
||||
}
|
||||
|
||||
static App: FC<()> = |cx, _| {
|
||||
let scene = use_state(cx, || Scene::ClientsList);
|
||||
let clients = use_ref(cx, || vec![] as Vec<Client>);
|
||||
static App: Component<()> = |cx| {
|
||||
let scene = use_state(&cx, || Scene::ClientsList);
|
||||
let clients = use_ref(&cx, || vec![] as Vec<Client>);
|
||||
|
||||
let firstname = use_state(cx, || String::new());
|
||||
let lastname = use_state(cx, || String::new());
|
||||
let description = use_state(cx, || String::new());
|
||||
let firstname = use_state(&cx, || String::new());
|
||||
let lastname = use_state(&cx, || String::new());
|
||||
let description = use_state(&cx, || String::new());
|
||||
|
||||
let scene = match *scene {
|
||||
Scene::ClientsList => {
|
||||
|
|
|
@ -21,10 +21,10 @@ fn main() {
|
|||
console_error_panic_hook::set_once();
|
||||
|
||||
// Run the app
|
||||
dioxus_web::launch(App, |c| c)
|
||||
dioxus_web::launch(App)
|
||||
}
|
||||
|
||||
pub static App: FC<()> = |cx, props| {
|
||||
pub static App: Component<()> = |cx| {
|
||||
cx.render(rsx!(
|
||||
div { class: "overflow-hidden"
|
||||
link { href:"https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel:"stylesheet" }
|
||||
|
@ -39,7 +39,7 @@ pub static App: FC<()> = |cx, props| {
|
|||
))
|
||||
};
|
||||
|
||||
pub static Header: FC<()> = |cx, props| {
|
||||
pub static Header: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
header { class: "text-gray-400 bg-gray-900 body-font"
|
||||
|
@ -65,7 +65,7 @@ pub static Header: FC<()> = |cx, props| {
|
|||
})
|
||||
};
|
||||
|
||||
pub static Hero: FC<()> = |cx, props| {
|
||||
pub static Hero: Component<()> = |cx| {
|
||||
//
|
||||
cx.render(rsx! {
|
||||
section{ class: "text-gray-400 bg-gray-900 body-font"
|
||||
|
@ -103,7 +103,7 @@ pub static Hero: FC<()> = |cx, props| {
|
|||
}
|
||||
})
|
||||
};
|
||||
pub static Entry: FC<()> = |cx, props| {
|
||||
pub static Entry: Component<()> = |cx| {
|
||||
//
|
||||
cx.render(rsx! {
|
||||
section{ class: "text-gray-400 bg-gray-900 body-font"
|
||||
|
@ -116,7 +116,7 @@ pub static Entry: FC<()> = |cx, props| {
|
|||
})
|
||||
};
|
||||
|
||||
pub static StacksIcon: FC<()> = |cx, props| {
|
||||
pub static StacksIcon: Component<()> = |cx| {
|
||||
cx.render(rsx!(
|
||||
svg {
|
||||
// xmlns: "http://www.w3.org/2000/svg"
|
||||
|
@ -131,7 +131,7 @@ pub static StacksIcon: FC<()> = |cx, props| {
|
|||
}
|
||||
))
|
||||
};
|
||||
pub static RightArrowIcon: FC<()> = |cx, props| {
|
||||
pub static RightArrowIcon: Component<()> = |cx| {
|
||||
cx.render(rsx!(
|
||||
svg {
|
||||
fill: "none"
|
||||
|
|
|
@ -16,10 +16,10 @@ fn main() {
|
|||
#[cfg(target_arch = "wasm32")]
|
||||
intern_strings();
|
||||
|
||||
dioxus::web::launch(App, |c| c);
|
||||
dioxus::web::launch(App);
|
||||
}
|
||||
|
||||
static App: Component<()> = |cx, props| {
|
||||
static App: Component<()> = |cx| {
|
||||
let mut rng = SmallRng::from_entropy();
|
||||
let rows = (0..1_000).map(|f| {
|
||||
let label = Label::new(&mut rng);
|
||||
|
@ -49,7 +49,7 @@ fn Row((cx, props): ScopeState<RowProps>) -> Element {
|
|||
let [adj, col, noun] = props.label.0;
|
||||
cx.render(rsx! {
|
||||
tr {
|
||||
td { class:"col-md-1", "{props.row_id}" }
|
||||
td { class:"col-md-1", "{cx.props.row_id}" }
|
||||
td { class:"col-md-1", onclick: move |_| { /* run onselect */ }
|
||||
a { class: "lbl", "{adj}" "{col}" "{noun}" }
|
||||
}
|
||||
|
|
|
@ -13,11 +13,11 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
dioxus::web::launch(App, |c| c);
|
||||
dioxus::web::launch(App);
|
||||
}
|
||||
|
||||
static App: Component<()> = |cx, props| {
|
||||
let mut count = use_state(cx, || 0);
|
||||
static App: Component<()> = |cx| {
|
||||
let mut count = use_state(&cx, || 0);
|
||||
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
|
|
|
@ -12,7 +12,7 @@ https://github.com/rustwasm/gloo
|
|||
For example, resize observer would function like this:
|
||||
|
||||
```rust
|
||||
pub static Example: FC<()> = |cx, props|{
|
||||
pub static Example: Component<()> = |cx, props|{
|
||||
let observer = use_resize_observer();
|
||||
|
||||
cx.render(rsx!(
|
||||
|
|
|
@ -153,13 +153,13 @@ Notice that LiveComponent receivers (the client-side interpretation of a LiveCom
|
|||
The `VNodeTree` type is a very special type that allows VNodes to be created using a pluggable allocator. The html! macro creates something that looks like:
|
||||
|
||||
```rust
|
||||
pub static Example: FC<()> = |cx, props|{
|
||||
pub static Example: Component<()> = |cx, props|{
|
||||
html! { <div> "blah" </div> }
|
||||
};
|
||||
|
||||
// expands to...
|
||||
|
||||
pub static Example: FC<()> = |cx, props|{
|
||||
pub static Example: Component<()> = |cx, props|{
|
||||
// This function converts a Fn(allocator) -> DomTree closure to a VNode struct that will later be evaluated.
|
||||
html_macro_to_vnodetree(move |allocator| {
|
||||
let mut node0 = allocator.alloc(VElement::div);
|
||||
|
@ -313,7 +313,7 @@ Here's how react does it:
|
|||
Any "dirty" node causes an entire subtree render. Calling "setState" at the very top will cascade all the way down. This is particularly bad for this component design:
|
||||
|
||||
```rust
|
||||
static APP: FC<()> = |cx, props|{
|
||||
static APP: Component<()> = |cx, props|{
|
||||
let title = use_context(Title);
|
||||
cx.render(html!{
|
||||
<div>
|
||||
|
@ -334,7 +334,7 @@ static APP: FC<()> = |cx, props|{
|
|||
</div>
|
||||
})
|
||||
};
|
||||
static HEAVY_LIST: FC<()> = |cx, props|{
|
||||
static HEAVY_LIST: Component<()> = |cx, props|{
|
||||
cx.render({
|
||||
{0.100.map(i => <BigElement >)}
|
||||
})
|
||||
|
@ -378,7 +378,7 @@ struct Props {
|
|||
|
||||
}
|
||||
|
||||
static Component: FC<Props> = |cx, props|{
|
||||
static Component: Component<Props> = |cx, props|{
|
||||
|
||||
}
|
||||
```
|
||||
|
|
|
@ -30,7 +30,7 @@ pub fn derive_typed_builder(input: proc_macro::TokenStream) -> proc_macro::Token
|
|||
///
|
||||
/// ## Complete Reference Guide:
|
||||
/// ```
|
||||
/// const Example: FC<()> = |cx, props|{
|
||||
/// const Example: Component<()> = |cx, props|{
|
||||
/// let formatting = "formatting!";
|
||||
/// let formatting_tuple = ("a", "b");
|
||||
/// let lazy_fmt = format_args!("lazily formatted text");
|
||||
|
|
|
@ -43,7 +43,11 @@ impl Parse for AmbiguousElement {
|
|||
if first_char.is_ascii_uppercase() {
|
||||
input.parse::<Component>().map(AmbiguousElement::Component)
|
||||
} else {
|
||||
input.parse::<Element>().map(AmbiguousElement::Element)
|
||||
if input.peek2(syn::token::Paren) {
|
||||
input.parse::<Component>().map(AmbiguousElement::Component)
|
||||
} else {
|
||||
input.parse::<Element>().map(AmbiguousElement::Element)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Err(Error::new(input.span(), "Not a valid Html tag"))
|
||||
|
|
|
@ -39,7 +39,14 @@ impl Parse for Component {
|
|||
|
||||
// parse the guts
|
||||
let content: ParseBuffer;
|
||||
syn::braced!(content in stream);
|
||||
|
||||
// if we see a `{` then we have a block
|
||||
// else parse as a function-like call
|
||||
if stream.peek(token::Brace) {
|
||||
syn::braced!(content in stream);
|
||||
} else {
|
||||
syn::parenthesized!(content in stream);
|
||||
}
|
||||
|
||||
let cfg: BodyConfig = BodyConfig {
|
||||
allow_children: true,
|
||||
|
|
|
@ -22,7 +22,7 @@ longest-increasing-subsequence = "0.1.0"
|
|||
# internall used
|
||||
log = { version = "0.4", features = ["release_max_level_off"] }
|
||||
|
||||
futures-util = { version = "0.3.15", default-features = false }
|
||||
futures-util = { version = "0.3", default-features = false }
|
||||
|
||||
smallvec = "1.6"
|
||||
|
||||
|
@ -48,7 +48,7 @@ fern = { version = "0.6.0", features = ["colored"] }
|
|||
rand = { version = "0.8.4", features = ["small_rng"] }
|
||||
simple_logger = "1.13.0"
|
||||
dioxus-core-macro = { path = "../core-macro", version = "0.1.2" }
|
||||
dioxus-hooks = { path = "../hooks" }
|
||||
# dioxus-hooks = { path = "../hooks" }
|
||||
criterion = "0.3.5"
|
||||
|
||||
[features]
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
This is the core crate for the Dioxus Virtual DOM. This README will focus on the technical design and layout of this Virtual DOM implementation. If you want to read more about using Dioxus, then check out the Dioxus crate, documentation, and website.
|
||||
|
||||
To build new apps with Dioxus or to extend the ecosystem with new hooks or components, use the `Dioxus` crate with the appropriate feature flags.
|
||||
To build new apps with Dioxus or to extend the ecosystem with new hooks or components, use the higher-level `dioxus` crate with the appropriate feature flags.
|
||||
|
||||
## Internals
|
||||
|
||||
|
@ -10,69 +10,44 @@ Dioxus-core builds off the many frameworks that came before it. Notably, Dioxus
|
|||
|
||||
- React: hooks, concurrency, suspense
|
||||
- Dodrio: bump allocation, double buffering, and some diffing architecture
|
||||
- Percy: html! macro architecture, platform-agnostic edits
|
||||
- InfernoJS: approach to keyed diffing
|
||||
- Preact: approach for normalization and ref
|
||||
- Yew: passion and inspiration ❤️
|
||||
|
||||
Dioxus-core leverages some really cool techniques and hits a very high level of parity with mature frameworks. However, Dioxus also brings some new unique features:
|
||||
|
||||
- managed lifetimes for borrowed data
|
||||
- suspended nodes (task/fiber endpoints) for asynchronous vnodes
|
||||
- placeholder approach for suspended vnodes
|
||||
- fiber/interruptible diffing algorithm
|
||||
- custom memory allocator for vnodes and all text content
|
||||
- support for fragments w/ lazy normalization
|
||||
- slab allocator for scopes
|
||||
- mirrored-slab approach for remote vdoms
|
||||
- dedicated subtrees for rendering into separate contexts from the same app
|
||||
|
||||
There's certainly more to the story, but these optimizations make Dioxus memory use and allocation count extremely minimal. For an average application, it is possible that zero allocations will need to be performed once the app has been mounted. Only when new components are added to the dom will allocations occur - and only en mass. The space of old VNodes is dynamically recycled as new nodes are added. Additionally, Dioxus tracks the average memory footprint of previous components to estimate how much memory allocate for future components.
|
||||
There's certainly more to the story, but these optimizations make Dioxus memory use and allocation count extremely minimal. For an average application, it is possible that zero allocations will need to be performed once the app has been loaded. Only when new components are added to the dom will allocations occur. For a given component, the space of old VNodes is dynamically recycled as new nodes are added. Additionally, Dioxus tracks the average memory footprint of previous components to estimate how much memory allocate for future components.
|
||||
|
||||
All in all, Dioxus treats memory as an incredibly valuable resource. Combined with the memory-efficient footprint of Wasm compilation, Dioxus apps can scale to thousands of components and still stay snappy and respect your RAM usage.
|
||||
All in all, Dioxus treats memory as a valuable resource. Combined with the memory-efficient footprint of Wasm compilation, Dioxus apps can scale to thousands of components and still stay snappy.
|
||||
|
||||
## Goals
|
||||
|
||||
We have big goals for Dioxus. The final implementation must:
|
||||
The final implementation of Dioxus must:
|
||||
|
||||
- Be **fast**. Allocators are typically slow in Wasm/Rust, so we should have a smart way of allocating.
|
||||
- Be extremely memory efficient. Servers should handle tens of thousands of simultaneous VDoms with no problem.
|
||||
- Be concurrent. Components should be able to pause rendering using a threading mechanism.
|
||||
- Be "remote". Edit lists should be separate from the Renderer implementation.
|
||||
- Support SSR. VNodes should render to a string that can be served via a web server.
|
||||
- Be memory efficient. Servers should handle tens of thousands of simultaneous VDoms with no problem.
|
||||
- Be concurrent. Components should be able to pause rendering to let the screen paint the next frame.
|
||||
- Be disconnected from a specific renderer (no WebSys dependency in the core crate).
|
||||
- Support server-side-rendering (SSR). VNodes should render to a string that can be served via a web server.
|
||||
- Be "live". Components should be able to be both server rendered and client rendered without needing frontend APIs.
|
||||
- Be modular. Components and hooks should be work anywhere without worrying about target platform.
|
||||
|
||||
|
||||
|
||||
## Safety
|
||||
|
||||
Dioxus uses unsafe. The design of Dioxus *requires* unsafe (self-referential trees).
|
||||
|
||||
All of our test suite passes MIRI without errors.
|
||||
|
||||
Dioxus deals with arenas, lifetimes, asynchronous tasks, custom allocators, pinning, and a lot more foundational low-level work that is very difficult to implement with 0 unsafe.
|
||||
|
||||
If you don't want to use a crate that uses unsafe, then this crate is not for you.
|
||||
|
||||
however, we are always interested in decreasing the scope of the core VirtualDom to make it easier to review.
|
||||
However, we are always interested in decreasing the scope of the core VirtualDom to make it easier to review. We'd be happy to welcome PRs that can eliminate unsafe code while still upholding the numerous variants required to execute certain features.
|
||||
|
||||
We'd also be happy to welcome PRs that can eliminate unsafe code while still upholding the numerous variants required to execute certain features.
|
||||
|
||||
There's a few invariants that are very important:
|
||||
|
||||
- References to `ScopeInner` and `Props` passed into components are *always* valid for as long as the component exists. Even if the scope backing is resized to fit more scopes, the scope has to stay the same place in memory.
|
||||
|
||||
|
||||
|
||||
## Suspense
|
||||
|
||||
Suspense is done through combinators on values.
|
||||
|
||||
```rust
|
||||
let name = get_name(cx).suspend();
|
||||
|
||||
rsx!(
|
||||
div {
|
||||
{name}
|
||||
div {
|
||||
div {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# Dioxus Core Architecture:
|
||||
|
||||
This document is mostly a brain-dump on how things work. A lot of this information might be outdated. Certain features (priority queues, swim lanes) might not be implemented yet.
|
||||
|
||||
Main topics covered here:
|
||||
- Fiber, Concurrency, and Cooperative Scheduling
|
||||
- Suspense
|
||||
|
|
|
@ -23,7 +23,7 @@ criterion_group!(mbenches, create_rows);
|
|||
criterion_main!(mbenches);
|
||||
|
||||
fn create_rows(c: &mut Criterion) {
|
||||
static App: Component<()> = |cx, _| {
|
||||
static App: Component<()> = |cx| {
|
||||
let mut rng = SmallRng::from_entropy();
|
||||
let rows = (0..10_000_usize).map(|f| {
|
||||
let label = Label::new(&mut rng);
|
||||
|
@ -53,11 +53,11 @@ struct RowProps {
|
|||
row_id: usize,
|
||||
label: Label,
|
||||
}
|
||||
fn Row(cx: Scope, props: &RowProps) -> Element {
|
||||
let [adj, col, noun] = props.label.0;
|
||||
fn Row(cx: Scope<RowProps>) -> Element {
|
||||
let [adj, col, noun] = cx.props.label.0;
|
||||
cx.render(rsx! {
|
||||
tr {
|
||||
td { class:"col-md-1", "{props.row_id}" }
|
||||
td { class:"col-md-1", "{cx.props.row_id}" }
|
||||
td { class:"col-md-1", onclick: move |_| { /* run onselect */ }
|
||||
a { class: "lbl", "{adj}" "{col}" "{noun}" }
|
||||
}
|
||||
|
|
|
@ -31,21 +31,3 @@ fn bleat() {
|
|||
let blah = String::from("asd");
|
||||
eat(&blah);
|
||||
}
|
||||
|
||||
// struct Lower {}
|
||||
|
||||
// #[derive(Clone, Copy)]
|
||||
// struct Upper {}
|
||||
// impl std::ops::Deref for Upper {
|
||||
// type Target = Lower;
|
||||
|
||||
// fn deref(&self) -> &Self::Target {
|
||||
// todo!()
|
||||
// }
|
||||
// }
|
||||
|
||||
// fn mark(f: &Lower) {}
|
||||
// fn bark() {
|
||||
// let up = Upper {};
|
||||
// mark(&up);
|
||||
// }
|
||||
|
|
|
@ -1,16 +1,10 @@
|
|||
use dioxus::prelude::*;
|
||||
use dioxus_core as dioxus;
|
||||
use dioxus_core_macro::*;
|
||||
use dioxus_hooks::use_state;
|
||||
use dioxus_html as dioxus_elements;
|
||||
|
||||
fn main() {}
|
||||
|
||||
fn App(cx: Scope<()>) -> Element {
|
||||
let color = use_state(&cx, || "white");
|
||||
|
||||
cx.render(rsx!(
|
||||
div { onclick: move |_| color.set("red"), "red" }
|
||||
div { onclick: move |_| color.set("blue"), "blue" }
|
||||
))
|
||||
todo!()
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 38 KiB |
|
@ -58,7 +58,7 @@ impl<'a, const A: bool> FragmentBuilder<'a, A> {
|
|||
/// cx.render(rsx!{
|
||||
/// div {
|
||||
/// h1 {"Title card"}
|
||||
/// {props.children}
|
||||
/// {cx.props.children}
|
||||
/// }
|
||||
/// })
|
||||
/// }
|
||||
|
|
|
@ -440,7 +440,7 @@ impl<'bump> DiffState<'bump> {
|
|||
let height = parent_scope.height + 1;
|
||||
let subtree = parent_scope.subtree.get();
|
||||
|
||||
let parent_scope = unsafe { self.scopes.get_scope_raw(parent_idx) };
|
||||
let parent_scope = self.scopes.get_scope_raw(parent_idx);
|
||||
let caller = unsafe { std::mem::transmute(vcomponent.caller as *const _) };
|
||||
let fc_ptr = vcomponent.user_fc;
|
||||
|
||||
|
@ -716,13 +716,12 @@ impl<'bump> DiffState<'bump> {
|
|||
new.associated_scope.set(Some(scope_addr));
|
||||
|
||||
// make sure the component's caller function is up to date
|
||||
let scope = unsafe {
|
||||
self.scopes
|
||||
.get_scope_mut(scope_addr)
|
||||
.unwrap_or_else(|| panic!("could not find {:?}", scope_addr))
|
||||
};
|
||||
let scope = self
|
||||
.scopes
|
||||
.get_scope(scope_addr)
|
||||
.unwrap_or_else(|| panic!("could not find {:?}", scope_addr));
|
||||
|
||||
scope.caller = unsafe { std::mem::transmute(new.caller) };
|
||||
scope.caller.set(unsafe { std::mem::transmute(new.caller) });
|
||||
|
||||
// React doesn't automatically memoize, but we do.
|
||||
let props_are_the_same = old.comparator.unwrap();
|
||||
|
|
|
@ -520,8 +520,8 @@ impl<'a> NodeFactory<'a> {
|
|||
move |other: &VComponent| {
|
||||
if user_fc == other.user_fc {
|
||||
// Safety
|
||||
// - We guarantee that FC<P> is the same by function pointer
|
||||
// - Because FC<P> is the same, then P must be the same (even with generics)
|
||||
// - We guarantee that Component<P> is the same by function pointer
|
||||
// - Because Component<P> is the same, then P must be the same (even with generics)
|
||||
// - Non-static P are autoderived to memoize as false
|
||||
// - This comparator is only called on a corresponding set of bumpframes
|
||||
//
|
||||
|
|
|
@ -28,7 +28,7 @@ use bumpalo::{boxed::Box as BumpBox, Bump};
|
|||
/// }
|
||||
///
|
||||
/// fn Example(cx: Context, props: &ExampleProps) -> Element {
|
||||
/// cx.render(rsx!{ div {"Hello, {props.name}"} })
|
||||
/// cx.render(rsx!{ div {"Hello, {cx.props.name}"} })
|
||||
/// }
|
||||
/// ```
|
||||
pub struct Scope<'a, P> {
|
||||
|
@ -88,7 +88,7 @@ pub struct ScopeState {
|
|||
|
||||
pub(crate) frames: [BumpFrame; 2],
|
||||
|
||||
pub(crate) caller: *const dyn Fn(&ScopeState) -> Element,
|
||||
pub(crate) caller: Cell<*const dyn Fn(&ScopeState) -> Element>,
|
||||
|
||||
pub(crate) items: RefCell<SelfReferentialItems<'static>>,
|
||||
|
||||
|
@ -269,12 +269,12 @@ impl ScopeState {
|
|||
/// ```rust, ignore
|
||||
/// struct SharedState(&'static str);
|
||||
///
|
||||
/// static App: FC<()> = |cx, props|{
|
||||
/// static App: Component<()> = |cx, props|{
|
||||
/// cx.use_hook(|_| cx.provide_state(SharedState("world")), |_| {}, |_| {});
|
||||
/// rsx!(cx, Child {})
|
||||
/// }
|
||||
///
|
||||
/// static Child: FC<()> = |cx, props| {
|
||||
/// static Child: Component<()> = |cx| {
|
||||
/// let state = cx.consume_state::<SharedState>();
|
||||
/// rsx!(cx, div { "hello {state.0}" })
|
||||
/// }
|
||||
|
@ -344,7 +344,7 @@ impl ScopeState {
|
|||
/// ## Example
|
||||
///
|
||||
/// ```ignore
|
||||
/// fn Component(cx: Scope, props: &Props) -> Element {
|
||||
/// fn Component(cx: Scope<Props>) -> Element {
|
||||
/// // Lazy assemble the VNode tree
|
||||
/// let lazy_nodes = rsx!("hello world");
|
||||
///
|
||||
|
|
|
@ -72,14 +72,10 @@ impl ScopeArena {
|
|||
unsafe { self.scopes.borrow().get(&id).map(|f| &**f) }
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn get_scope_raw(&self, id: ScopeId) -> Option<*mut ScopeState> {
|
||||
pub(crate) fn get_scope_raw(&self, id: ScopeId) -> Option<*mut ScopeState> {
|
||||
self.scopes.borrow().get(&id).copied()
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn get_scope_mut(&self, id: ScopeId) -> Option<&mut ScopeState> {
|
||||
self.scopes.borrow().get(&id).map(|s| &mut **s)
|
||||
}
|
||||
|
||||
pub(crate) fn new_with_key(
|
||||
&self,
|
||||
fc_ptr: *const (),
|
||||
|
@ -95,35 +91,13 @@ impl ScopeArena {
|
|||
if let Some(old_scope) = self.free_scopes.borrow_mut().pop() {
|
||||
let scope = unsafe { &mut *old_scope };
|
||||
|
||||
scope.caller = caller;
|
||||
scope.caller.set(caller);
|
||||
scope.parent_scope = parent_scope;
|
||||
scope.height = height;
|
||||
scope.subtree = Cell::new(subtree);
|
||||
scope.our_arena_idx = new_scope_id;
|
||||
scope.container = container;
|
||||
|
||||
// scope.frames[0].nodes.get_mut().push({
|
||||
// let vnode = scope.frames[0]
|
||||
// .bump
|
||||
// .alloc(VNode::Text(scope.frames[0].bump.alloc(VText {
|
||||
// dom_id: Default::default(),
|
||||
// is_static: false,
|
||||
// text: "",
|
||||
// })));
|
||||
// unsafe { std::mem::transmute(vnode as *mut VNode) }
|
||||
// });
|
||||
|
||||
// scope.frames[1].nodes.get_mut().push({
|
||||
// let vnode = scope.frames[1]
|
||||
// .bump
|
||||
// .alloc(VNode::Text(scope.frames[1].bump.alloc(VText {
|
||||
// dom_id: Default::default(),
|
||||
// is_static: false,
|
||||
// text: "",
|
||||
// })));
|
||||
// unsafe { std::mem::transmute(vnode as *mut VNode) }
|
||||
// });
|
||||
|
||||
let any_item = self.scopes.borrow_mut().insert(new_scope_id, scope);
|
||||
debug_assert!(any_item.is_none());
|
||||
} else {
|
||||
|
@ -148,7 +122,7 @@ impl ScopeArena {
|
|||
subtree: Cell::new(subtree),
|
||||
is_subtree_root: Cell::new(false),
|
||||
|
||||
caller,
|
||||
caller: Cell::new(caller),
|
||||
generation: 0.into(),
|
||||
|
||||
shared_contexts: Default::default(),
|
||||
|
@ -277,18 +251,20 @@ impl ScopeArena {
|
|||
// Remove all the outdated listeners
|
||||
self.ensure_drop_safety(id);
|
||||
|
||||
let scope = unsafe { &mut *self.get_scope_mut(id).expect("could not find scope") };
|
||||
// todo: we *know* that this is aliased by the contents of the scope itself
|
||||
let scope = unsafe { &mut *self.get_scope_raw(id).expect("could not find scope") };
|
||||
|
||||
// Safety:
|
||||
// - We dropped the listeners, so no more &mut T can be used while these are held
|
||||
// - All children nodes that rely on &mut T are replaced with a new reference
|
||||
scope.hook_idx.set(0);
|
||||
|
||||
// Safety:
|
||||
// - We've dropped all references to the wip bump frame with "ensure_drop_safety"
|
||||
unsafe { scope.reset_wip_frame() };
|
||||
|
||||
// book keeping to ensure safety around the borrowed data
|
||||
{
|
||||
// Safety:
|
||||
// - We've dropped all references to the wip bump frame with "ensure_drop_safety"
|
||||
unsafe { scope.reset_wip_frame() };
|
||||
|
||||
let mut items = scope.items.borrow_mut();
|
||||
|
||||
// just forget about our suspended nodes while we're at it
|
||||
|
@ -298,12 +274,9 @@ impl ScopeArena {
|
|||
debug_assert!(items.listeners.is_empty());
|
||||
debug_assert!(items.borrowed_props.is_empty());
|
||||
debug_assert!(items.tasks.is_empty());
|
||||
|
||||
// Todo: see if we can add stronger guarantees around internal bookkeeping and failed component renders.
|
||||
// scope.wip_frame().nodes
|
||||
}
|
||||
|
||||
let render: &dyn Fn(&ScopeState) -> Element = unsafe { &*scope.caller };
|
||||
let render: &dyn Fn(&ScopeState) -> Element = unsafe { &*scope.caller.get() };
|
||||
|
||||
if let Some(node) = render(scope) {
|
||||
if !scope.items.borrow().tasks.is_empty() {
|
||||
|
@ -319,6 +292,10 @@ impl ScopeArena {
|
|||
scope.cycle_frame();
|
||||
true
|
||||
} else {
|
||||
// the component bailed out early
|
||||
// this leaves the wip frame and all descendents in a state where
|
||||
// their WIP frames are invalid
|
||||
// todo: descendents should not cause the app to crash
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ use std::{any::Any, collections::VecDeque, pin::Pin, sync::Arc, task::Poll};
|
|||
///
|
||||
/// fn App(cx: Context, props: &AppProps) -> Element {
|
||||
/// cx.render(rsx!(
|
||||
/// div {"hello, {props.title}"}
|
||||
/// div {"hello, {cx.props.title}"}
|
||||
/// ))
|
||||
/// }
|
||||
/// ```
|
||||
|
@ -36,7 +36,7 @@ use std::{any::Any, collections::VecDeque, pin::Pin, sync::Arc, task::Poll};
|
|||
/// fn App(cx: Context, props: &AppProps) -> Element {
|
||||
/// cx.render(rsx!(
|
||||
/// NavBar { routes: ROUTES }
|
||||
/// Title { "{props.title}" }
|
||||
/// Title { "{cx.props.title}" }
|
||||
/// Footer {}
|
||||
/// ))
|
||||
/// }
|
||||
|
@ -459,7 +459,7 @@ impl VirtualDom {
|
|||
///
|
||||
/// # Example
|
||||
/// ```rust, ignore
|
||||
/// static App: FC<()> = |cx, props| cx.render(rsx!{ "hello world" });
|
||||
/// static App: Component<()> = |cx, props| cx.render(rsx!{ "hello world" });
|
||||
/// let mut dom = VirtualDom::new();
|
||||
/// let edits = dom.rebuild();
|
||||
///
|
||||
|
@ -497,7 +497,7 @@ impl VirtualDom {
|
|||
/// value: Shared<&'static str>,
|
||||
/// }
|
||||
///
|
||||
/// static App: FC<AppProps> = |cx, props|{
|
||||
/// static App: Component<AppProps> = |cx, props|{
|
||||
/// let val = cx.value.borrow();
|
||||
/// cx.render(rsx! { div { "{val}" } })
|
||||
/// };
|
||||
|
|
|
@ -7,7 +7,6 @@ use dioxus_core::DomEdit::*;
|
|||
use dioxus_core::ScopeId;
|
||||
|
||||
use dioxus_core_macro::*;
|
||||
use dioxus_hooks::*;
|
||||
use dioxus_html as dioxus_elements;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@ This crate provides an ergonomic API for Dioxus to build desktop apps.
|
|||
|
||||
```rust
|
||||
fn main() {
|
||||
dioxus::desktop::launch(App, |c| c)
|
||||
dioxus::desktop::launch(App)
|
||||
}
|
||||
|
||||
static App: FC<()> = |cx, props| {
|
||||
let (count, set_count) = use_state(cx, || 0);
|
||||
static App: Component<()> = |cx| {
|
||||
let (count, set_count) = use_state(&cx, || 0);
|
||||
|
||||
cx.render(rsx!(
|
||||
WebviewWindow {
|
||||
|
@ -34,7 +34,7 @@ Window management, system trays, notifications, and other desktop-related functi
|
|||
Managing windows is done by simply rendering content into a `WebviewWindow` component.
|
||||
|
||||
```rust
|
||||
static App: FC<()> = |cx, props| {
|
||||
static App: Component<()> = |cx| {
|
||||
rsx!(cx, WebviewWindow { "hello world" } )
|
||||
}
|
||||
```
|
||||
|
@ -46,7 +46,7 @@ Notifications also use a declarative approach. Sending a notification has never
|
|||
The api has been somewhat modeled after https://github.com/mikaelbr/node-notifier
|
||||
|
||||
```rust
|
||||
static Notifications: FC<()> = |cx, props| {
|
||||
static Notifications: Component<()> = |cx| {
|
||||
cx.render(rsx!(
|
||||
Notification {
|
||||
title: "title"
|
||||
|
@ -78,7 +78,7 @@ static Notifications: FC<()> = |cx, props| {
|
|||
Dioxus Desktop supports app trays, which can be built with native menu groups or with a custom window.
|
||||
|
||||
```rust
|
||||
static Tray: FC<()> = |cx, props| {
|
||||
static Tray: Component<()> = |cx| {
|
||||
cx.render(rsx!(
|
||||
GlobalTray {
|
||||
MenuGroup {
|
||||
|
@ -90,7 +90,7 @@ static Tray: FC<()> = |cx, props| {
|
|||
};
|
||||
|
||||
// using a builder
|
||||
static Tray: FC<()> = |cx, props| {
|
||||
static Tray: Component<()> = |cx| {
|
||||
let menu = MenuGroup::builder(cx)
|
||||
.with_items([
|
||||
MenuGroupItem::builder()
|
||||
|
@ -107,7 +107,7 @@ static Tray: FC<()> = |cx, props| {
|
|||
}
|
||||
|
||||
// or with a custom window
|
||||
static Tray: FC<()> = |cx, props| {
|
||||
static Tray: Component<()> = |cx| {
|
||||
rsx!(cx, GlobalTray { div { "custom buttons here" } })
|
||||
};
|
||||
```
|
||||
|
@ -116,7 +116,7 @@ static Tray: FC<()> = |cx, props| {
|
|||
Declaring menus is convenient and cross-platform.
|
||||
|
||||
```rust
|
||||
static Menu: FC<()> = |cx, props| {
|
||||
static Menu: Component<()> = |cx| {
|
||||
cx.render(rsx!(
|
||||
MenuBarMajorItem { title: "File"
|
||||
MenuGroup {
|
||||
|
|
|
@ -12,11 +12,11 @@ use dioxus_html as dioxus_elements;
|
|||
|
||||
fn main() {
|
||||
simple_logger::init().unwrap();
|
||||
dioxus_desktop::launch(App, |c| c);
|
||||
dioxus_desktop::launch(app);
|
||||
}
|
||||
|
||||
static App: Component<()> = |cx, props| {
|
||||
let mut count = use_state(cx, || 0);
|
||||
fn app(cx: Scope<()>) -> Element {
|
||||
let mut count = use_state(&cx, || 0);
|
||||
log::debug!("count is {:?}", count);
|
||||
|
||||
cx.push_task(|| async move {
|
||||
|
|
|
@ -90,7 +90,7 @@ fn syntax_works() {
|
|||
use dioxus_hooks::*;
|
||||
use dioxus_html as dioxus_elements;
|
||||
|
||||
static App: FC<()> = |cx, props| {
|
||||
static App: Component<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
// left window
|
||||
WebviewWindow {
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
mod cfg;
|
||||
mod escape;
|
||||
mod events;
|
||||
pub use wry;
|
||||
pub use wry::application as tao;
|
||||
|
||||
// mod desktop_context;
|
||||
|
||||
use cfg::DesktopConfig;
|
||||
|
@ -28,7 +31,10 @@ use wry::{
|
|||
webview::{WebView, WebViewBuilder},
|
||||
};
|
||||
|
||||
pub fn launch(
|
||||
pub fn launch(root: Component<()>) {
|
||||
launch_with_props(root, (), |c| c)
|
||||
}
|
||||
pub fn launch_cfg(
|
||||
root: Component<()>,
|
||||
config_builder: impl for<'a, 'b> FnOnce(&'b mut DesktopConfig<'a>) -> &'b mut DesktopConfig<'a>,
|
||||
) {
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
[package]
|
||||
name = "dioxus-hooks"
|
||||
version = "0.0.0"
|
||||
version = "0.1.3"
|
||||
authors = ["Jonathan Kelley <jkelleyrtp@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
dioxus-core = { path = "../../packages/core", version = "0.1.3" }
|
||||
futures = "0.3"
|
||||
dioxus-core = { path = "../../packages/core" }
|
||||
|
|
|
@ -16,10 +16,10 @@ You can always use it "normally" with the `split` method:
|
|||
|
||||
```rust
|
||||
// Normal usage:
|
||||
let value = use_state(cx, || 10);
|
||||
let value = use_state(&cx, || 10);
|
||||
|
||||
// "Classic" usage:
|
||||
let (value, set_value) = use_state(cx, || 0).split();
|
||||
let (value, set_value) = use_state(&cx, || 0).split();
|
||||
```
|
||||
|
||||
## use_ref
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
mod usestate;
|
||||
pub use usestate::{use_state, AsyncUseState, UseState};
|
||||
|
||||
mod usestate2;
|
||||
// pub use usestate2::use_state2;
|
||||
|
||||
mod useref;
|
||||
pub use useref::*;
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue