feat: massage lifetimes

This commit is contained in:
Jonathan Kelley 2021-10-16 17:37:28 -04:00
parent 16dbf4a6f8
commit 9726a065b0
92 changed files with 250 additions and 241 deletions

View file

@ -49,7 +49,7 @@
Dioxus is a portable, performant, and ergonomic framework for building cross-platform user experiences in Rust.
```rust
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
let mut count = use_state(cx, || 0);
cx.render(rsx!(
@ -96,28 +96,6 @@ If you know React, then you already know Dioxus.
See the awesome-dioxus page for a curated list of content in the Dioxus Ecosystem.
<!--
currently commented out until we have more content on the website
## Explore
- [**Fine-grained reactivity**: Skip the diff overhead with signals ](docs/guides/00-index.md)
- [**HTML Templates**: Drop in existing HTML5 templates with html! macro](docs/guides/00-index.md)
- [**RSX Templates**: Clean component design with rsx! macro](docs/guides/00-index.md)
- [**Running the examples**: Explore the vast collection of samples, tutorials, and demos](docs/guides/00-index.md)
- [**Building applications**: Use the Dioxus CLI to build and bundle apps for various platforms](docs/guides/01-ssr.md)
- [**Liveview**: Build custom liveview components that simplify datafetching on all platforms](docs/guides/01-ssr.md)
- [**State management**: Easily add powerful state management that comes integrated with Dioxus Core](docs/guides/01-ssr.md)
- [**Concurrency**: Drop in async where it fits and suspend components until new data is ready](docs/guides/01-ssr.md)
- [**1st party hooks**: Cross-platform router hook](docs/guides/01-ssr.md)
- [**Community hooks**: 3D renderers](docs/guides/01-ssr.md)
## Blog Posts
- [Why we need a stronger typed web]()
- [Isomorphic webapps in 10 minutes]()
- [Rust is high level too]()
- [Eliminating crashes with Rust webapps]()
- [Tailwind for Dioxus]()
- [The monoglot startup]()
-->
## Why?
TypeScript is a great addition to JavaScript, but comes with a lot of tweaking flags, a slight performance hit, and an uneven ecosystem where some of the most important packages are not properly typed. TypeScript provides a lot of great benefits to JS projects, but comes with its own "tax" that can slow down dev teams. Rust can be seen as a step up from TypeScript, supporting:
@ -130,7 +108,7 @@ TypeScript is a great addition to JavaScript, but comes with a lot of tweaking f
- integrated documentation
- inline built-in unit/integration testing
- best-in-class error handling
- simple and fast build system (compared to webpack!)
- simple and fast build system (compared to WebPack!)
- powerful standard library (no need for lodash or underscore)
- include_str! for integrating html/css/svg templates directly
- various macros (`html!`, `rsx!`) for fast template iteration

View file

@ -6,7 +6,7 @@
```rust, ignore
// An example Dioxus app - closely resembles React
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
let mut count = use_state(cx, || 0);
cx.render(rsx!(

View file

@ -50,8 +50,8 @@ async fn ExampleLoader(cx: Context<()>) -> Vnode {
This API stores the result on the Context object, so the loaded data is taken as reference.
*/
let name: &Result<SomeStructure> = use_fetch_data("http://example.com/json", ())
.place_holder(|cx, props|rsx!{<div> "loading..." </div>})
.delayed_place_holder(1000, |cx, props|rsx!{ <div> "still loading..." </div>})
.place_holder(|(cx, props)|rsx!{<div> "loading..." </div>})
.delayed_place_holder(1000, |(cx, props)|rsx!{ <div> "still loading..." </div>})
.await;
match name {

View file

@ -21,9 +21,9 @@ fn test() -> DomTree {
}
}
static TestComponent: FC<()> = |cx, props|html!{<div>"Hello world"</div>};
static TestComponent: FC<()> = |(cx, props)|html!{<div>"Hello world"</div>};
static TestComponent: FC<()> = |cx, props|{
static TestComponent: FC<()> = |(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: FC<{ name: String }> = |(cx, props)|html! { <div> "Hello {name}" </div> };
```
## Why this behavior?

View file

@ -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: FC<()> = |(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: FC<()> = |(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: FC<()> = |(cx, props)|{
let dict = use_signal(&cx, &DICT);
cx.render(rsx!(
ul {

View file

@ -85,7 +85,7 @@ fn main() {
dioxus::desktop::start(App, |c| c);
}
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
cx.render(rsx! (
div { "Hello, world!" }
))
@ -111,7 +111,7 @@ fn main() {
Finally, our app. Every component in Dioxus is a function that takes in `Context` and `Props` and returns an `Option<VNode>`.
```rust
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
cx.render(rsx! {
div { "Hello, world!" }
})
@ -149,7 +149,7 @@ If we wanted to golf a bit, we can shrink our hello-world even smaller:
```rust
fn main() {
static App: FC<()> = |cx, props| rsx!(cx, div {"hello world!"});
static App: FC<()> = |(cx, props)| rsx!(cx, div {"hello world!"});
dioxus::web::start(App, |c| c);
}
```

View file

@ -11,7 +11,7 @@ async fn main() {
dioxus::desktop::launch(App, |c| c);
}
pub static App: FC<()> = |cx, _| {
pub static App: FC<()> = |(cx, _)| {
let count = use_state(cx, || 0);
let mut direction = use_state(cx, || 1);

View file

@ -20,8 +20,8 @@ fn main() {
dioxus::desktop::launch(App, |c| c);
}
fn App<'a>(cx: Context<'a>, props: &()) -> DomTree<'a> {
let text: &'a mut Vec<String> = cx.use_hook(|_| vec![String::from("abc=def")], |f| f, |_| {});
fn App((cx, props): Component<()>) -> DomTree {
let text: &mut Vec<String> = cx.use_hook(|_| vec![String::from("abc=def")], |f| f, |_| {});
let first = text.get_mut(0).unwrap();
@ -43,7 +43,7 @@ impl<'a> Drop for C1Props<'a> {
fn drop(&mut self) {}
}
fn Child1<'a>(cx: Context<'a>, props: &'a C1Props) -> DomTree<'a> {
fn Child1<'a>((cx, props): Component<'a, C1Props>) -> DomTree<'a> {
let (left, right) = props.text.split_once("=").unwrap();
cx.render(rsx! {
@ -58,13 +58,8 @@ fn Child1<'a>(cx: Context<'a>, props: &'a C1Props) -> DomTree<'a> {
struct C2Props<'a> {
text: &'a str,
}
impl<'a> Drop for C2Props<'a> {
fn drop(&mut self) {
todo!()
}
}
fn Child2<'a>(cx: Context<'a>, props: &'a C2Props) -> DomTree<'a> {
fn Child2<'a>((cx, props): Component<'a, C2Props>) -> DomTree<'a> {
cx.render(rsx! {
Child3 {
text: props.text
@ -77,7 +72,7 @@ struct C3Props<'a> {
text: &'a str,
}
fn Child3<'a>(cx: Context<'a>, props: &C3Props) -> DomTree<'a> {
fn Child3<'a>((cx, props): Component<'a, C3Props>) -> DomTree<'a> {
cx.render(rsx! {
div { "{props.text}"}
})

View file

@ -10,7 +10,7 @@ fn main() {
dioxus::desktop::launch(APP, |cfg| cfg);
}
const APP: FC<()> = |cx, _| {
const APP: FC<()> = |(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(""));
@ -116,7 +116,7 @@ struct CalculatorKeyProps<'a> {
onclick: &'a dyn Fn(MouseEvent),
}
fn CalculatorKey<'a>(cx: Context<'a>, props: &'a CalculatorKeyProps) -> DomTree<'a> {
fn CalculatorKey<'a>((cx, props): Component<'a, CalculatorKeyProps>) -> DomTree<'a> {
rsx!(cx, button {
class: "calculator-key {props.name}"
onclick: {props.onclick}

View file

@ -27,7 +27,7 @@ fn main() {
use dioxus::prelude::*;
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
let p1 = use_state(cx, || 0);
let p2 = use_state(cx, || 0);
@ -59,7 +59,7 @@ struct HorseyProps {
pos: i32,
}
static Horsey: FC<HorseyProps> = |cx, props| {
static Horsey: FC<HorseyProps> = |(cx, props)| {
cx.render(rsx! {
div {
button { "pause" }

View file

@ -19,7 +19,7 @@ pub struct Client {
pub description: String,
}
static App: FC<()> = |cx, _| {
static App: FC<()> = |(cx, _)| {
let clients = use_ref(cx, || vec![] as Vec<Client>);
let scene = use_state(cx, || Scene::ClientsList);

View file

@ -18,7 +18,7 @@ fn main() {
});
}
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
let file_manager = use_ref(cx, || Files::new());
let files = file_manager.read();

View file

@ -9,7 +9,7 @@ fn main() {
// We use a special immutable hashmap to make hashmap operations efficient
type RowList = im_rc::HashMap<usize, Rc<str>, FxBuildHasher>;
static App: FC<()> = |cx, _props| {
static App: FC<()> = |(cx, _props)| {
let items = use_state(cx, || RowList::default());
let create_rendered_rows = move |from, num| move |_| items.set(create_row_list(from, num));
@ -80,7 +80,7 @@ struct ActionButtonProps<'a> {
onclick: &'a dyn Fn(MouseEvent),
}
fn ActionButton<'a>(cx: Context<'a>, props: &'a ActionButtonProps) -> DomTree<'a> {
fn ActionButton<'a>((cx, props): Component<'a, ActionButtonProps>) -> DomTree<'a> {
rsx!(cx, div { class: "col-sm-6 smallpad"
button { class:"btn btn-primary btn-block", r#type: "button", id: "{props.id}", onclick: {props.onclick},
"{props.name}"
@ -93,7 +93,7 @@ struct RowProps {
row_id: usize,
label: Rc<str>,
}
fn Row<'a>(cx: Context<'a>, props: &'a RowProps) -> DomTree<'a> {
fn Row((cx, props): Component<RowProps>) -> DomTree {
rsx!(cx, tr {
td { class:"col-md-1", "{props.row_id}" }
td { class:"col-md-1", onclick: move |_| { /* run onselect */ }

View file

@ -19,7 +19,7 @@ fn main() {
dioxus::desktop::launch(App, |c| c.with_prerendered(content));
}
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
let mut val = use_state(cx, || 0);
cx.render(rsx! {

View file

@ -36,7 +36,7 @@ fn main() {
dioxus_desktop::run(APP, (), |c| c.with_edits(edits));
}
const APP: FC<()> = |cx, _props| {
const APP: FC<()> = |(cx, _props)| {
rsx!(cx, div {
"some app"
})

View file

@ -31,7 +31,7 @@ fn main() {
});
}
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
let state = use_ref(cx, || Calculator::new());
let clear_display = state.read().display_value.eq("0");
@ -76,7 +76,7 @@ struct CalculatorKeyProps<'a> {
onclick: &'a dyn Fn(MouseEvent),
}
fn CalculatorKey<'a, 'r>(cx: Context<'a>, props: &'a CalculatorKeyProps) -> DomTree<'a> {
fn CalculatorKey<'a>((cx, props): Component<'a, CalculatorKeyProps>) -> DomTree<'a> {
cx.render(rsx! {
button {
class: "calculator-key {props.name}"

View file

@ -11,7 +11,7 @@ fn main() {
dioxus::desktop::launch(App, |c| c);
}
pub static App: FC<()> = |cx, _| {
pub static App: FC<()> = |(cx, _)| {
let state = use_state(cx, PlayerState::new);
let is_playing = state.is_playing();

View file

@ -7,7 +7,7 @@ fn main() {
dioxus::desktop::launch(App, |c| c);
}
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
let mut count = use_state(cx, || 0);
cx.render(rsx! {

View file

@ -49,7 +49,7 @@ const NONE_ELEMENT: Option<()> = None;
use baller::Baller;
use dioxus::prelude::*;
pub static Example: FC<()> = |cx, props| {
pub static Example: FC<()> = |(cx, props)| {
let formatting = "formatting!";
let formatting_tuple = ("a", "b");
let lazy_fmt = format_args!("lazily formatted text");
@ -184,7 +184,7 @@ mod baller {
pub struct BallerProps {}
/// This component totally balls
pub fn Baller<'a>(cx: Context<'a>, props: &BallerProps) -> DomTree<'a> {
pub fn Baller(_: Component<BallerProps>) -> DomTree {
todo!()
}
}
@ -195,7 +195,7 @@ pub struct TallerProps {
}
/// This component is taller than most :)
pub fn Taller<'a>(cx: Context<'a>, props: &'a TallerProps) -> DomTree<'a> {
pub fn Taller(_: Component<TallerProps>) -> DomTree {
let b = true;
todo!()
}

View file

@ -9,7 +9,7 @@ fn main() {
println!("{}", ssr::render_vdom(&vdom, |c| c));
}
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
cx.render(rsx!(
div {
h1 { "Title" }

View file

@ -14,7 +14,7 @@ fn main() {
const STYLE: &str = "body {overflow:hidden;}";
pub static App: FC<()> = |cx, props| {
pub static App: FC<()> = |(cx, props)| {
cx.render(rsx!(
div { class: "overflow-hidden"
style { "{STYLE}" }
@ -30,7 +30,7 @@ pub static App: FC<()> = |cx, props| {
))
};
pub static Header: FC<()> = |cx, props| {
pub static Header: FC<()> = |(cx, props)| {
cx.render(rsx! {
div {
header { class: "text-gray-400 bg-gray-900 body-font"
@ -56,7 +56,7 @@ pub static Header: FC<()> = |cx, props| {
})
};
pub static Hero: FC<()> = |cx, props| {
pub static Hero: FC<()> = |(cx, props)| {
//
cx.render(rsx! {
section{ class: "text-gray-400 bg-gray-900 body-font"
@ -94,7 +94,7 @@ pub static Hero: FC<()> = |cx, props| {
}
})
};
pub static Entry: FC<()> = |cx, props| {
pub static Entry: FC<()> = |(cx, props)| {
//
cx.render(rsx! {
section{ class: "text-gray-400 bg-gray-900 body-font"
@ -107,7 +107,7 @@ pub static Entry: FC<()> = |cx, props| {
})
};
pub static StacksIcon: FC<()> = |cx, props| {
pub static StacksIcon: FC<()> = |(cx, props)| {
cx.render(rsx!(
svg {
// xmlns: "http://www.w3.org/2000/svg"
@ -122,7 +122,7 @@ pub static StacksIcon: FC<()> = |cx, props| {
}
))
};
pub static RightArrowIcon: FC<()> = |cx, props| {
pub static RightArrowIcon: FC<()> = |(cx, props)| {
cx.render(rsx!(
svg {
fill: "none"

View file

@ -22,7 +22,7 @@ pub struct TodoItem {
}
const STYLE: &str = include_str!("./assets/todomvc.css");
const App: FC<()> = |cx, props| {
const App: FC<()> = |(cx, props)| {
let draft = use_state(cx, || "".to_string());
let todos = use_state(cx, || HashMap::<u32, Rc<TodoItem>>::new());
let filter = use_state(cx, || FilterState::All);
@ -85,7 +85,7 @@ pub struct TodoEntryProps {
todo: Rc<TodoItem>,
}
pub fn TodoEntry<'a>(cx: Context<'a>, props: &TodoEntryProps) -> DomTree<'a> {
pub fn TodoEntry((cx, props): Component<TodoEntryProps>) -> DomTree {
let is_editing = use_state(cx, || false);
let contents = use_state(cx, || String::from(""));
let todo = &props.todo;

View file

@ -12,7 +12,7 @@ fn main() {
const ENDPOINT: &str = "https://api.openweathermap.org/data/2.5/weather";
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
//
let body = use_suspense(
cx,
@ -38,7 +38,7 @@ static App: FC<()> = |cx, props| {
#[derive(PartialEq, Props)]
struct WeatherProps {}
static WeatherDisplay: FC<WeatherProps> = |cx, props| {
static WeatherDisplay: FC<WeatherProps> = |(cx, props)| {
//
cx.render(rsx!(
div { class: "flex items-center justify-center flex-col"

View file

@ -19,7 +19,7 @@ fn main() {
dioxus::web::launch(App, |c| c);
}
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
let mut rng = SmallRng::from_entropy();
let rows = (0..1_000).map(|f| {
let label = Label::new(&mut rng);
@ -45,7 +45,7 @@ struct RowProps {
row_id: usize,
label: Label,
}
fn Row<'a>(cx: Context<'a>, props: &'a RowProps) -> DomTree<'a> {
fn Row((cx, props): Component<RowProps>) -> DomTree {
let [adj, col, noun] = props.label.0;
cx.render(rsx! {
tr {

View file

@ -16,7 +16,7 @@ fn main() {
dioxus::web::launch(App, |c| c);
}
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
let mut count = use_state(cx, || 0);
cx.render(rsx! {

View file

@ -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: FC<()> = |(cx, props)|{
let observer = use_resize_observer();
cx.render(rsx!(

View file

@ -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: FC<()> = |(cx, props)|{
html! { <div> "blah" </div> }
};
// expands to...
pub static Example: FC<()> = |cx, props|{
pub static Example: FC<()> = |(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: FC<()> = |(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: FC<()> = |(cx, props)|{
cx.render({
{0.100.map(i => <BigElement >)}
})
@ -378,7 +378,7 @@ struct Props {
}
static Component: FC<Props> = |cx, props|{
static Component: FC<Props> = |(cx, props)|{
}
```

View file

@ -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: FC<()> = |(cx, props)|{
/// let formatting = "formatting!";
/// let formatting_tuple = ("a", "b");
/// let lazy_fmt = format_args!("lazily formatted text");

View file

@ -72,7 +72,7 @@ impl ToTokens for RsxTemplate {
// // create a lazy tree that accepts a bump allocator
// let final_tokens = quote! {
// dioxus::prelude::LazyNodes::new(move |cx, props|{
// dioxus::prelude::LazyNodes::new(move |(cx, props)|{
// let bump = &cx.bump();
// #new_toks

View file

@ -23,7 +23,7 @@ criterion_group!(mbenches, create_rows);
criterion_main!(mbenches);
fn create_rows(c: &mut Criterion) {
static App: FC<()> = |cx, _| {
static App: FC<()> = |(cx, _)| {
let mut rng = SmallRng::from_entropy();
let rows = (0..10_000_usize).map(|f| {
let label = Label::new(&mut rng);
@ -57,7 +57,7 @@ struct RowProps {
row_id: usize,
label: Label,
}
fn Row<'a>(cx: Context<'a>, props: &RowProps) -> DomTree<'a> {
fn Row((cx, props): Component<RowProps>) -> DomTree {
let [adj, col, noun] = props.label.0;
cx.render(rsx! {
tr {

View file

@ -6,7 +6,7 @@ fn main() {
println!("{}", dom);
}
pub static EXAMPLE: FC<()> = |cx, _| {
pub static EXAMPLE: FC<()> = |(cx, _)| {
let list = (0..10).map(|_f| LazyNodes::new(move |_f| todo!()));
cx.render(LazyNodes::new(move |cx| {

View file

@ -5,7 +5,7 @@ fn main() {
dom.rebuild();
}
const App: FC<()> = |cx, props| {
const App: FC<()> = |(cx, props)| {
let id = cx.scope_id();
cx.submit_task(Box::pin(async move { id }));

View file

@ -6,7 +6,7 @@ struct SomeContext {
}
#[allow(unused)]
static Example: FC<()> = |cx, props| {
static Example: FC<()> = |(cx, props)| {
todo!()
// let value = cx.use_context(|c: &SomeContext| c.items.last().unwrap());

View file

@ -1,3 +1,4 @@
use dioxus::component::Component;
use dioxus::events::on::MouseEvent;
use dioxus_core as dioxus;
use dioxus_core::prelude::*;
@ -12,7 +13,7 @@ fn main() {
assert!(g.edits.len() > 1);
}
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
let mut rng = SmallRng::from_entropy();
let rows = (0..10_000_usize).map(|f| {
let label = Label::new(&mut rng);
@ -37,7 +38,7 @@ struct RowProps {
row_id: usize,
label: Label,
}
fn Row<'a>(cx: Context<'a>, props: &'a RowProps) -> DomTree<'a> {
fn Row((cx, props): Component<RowProps>) -> DomTree {
let handler = move |evt: MouseEvent| {
let g = evt.button;
};

View file

@ -4,7 +4,7 @@ use dioxus_core::prelude::*;
#[async_std::main]
async fn main() {
static App: FC<()> = |cx, props| cx.render(LazyNodes::new(|f| f.text(format_args!("hello"))));
static App: FC<()> = |(cx, props)| cx.render(LazyNodes::new(|f| f.text(format_args!("hello"))));
let mut dom = VirtualDom::new(App);

View file

@ -7,6 +7,40 @@
use crate::innerlude::{Context, DomTree, LazyNodes, FC};
/// A component is a wrapper around a Context and some Props that share a lifetime
///
///
/// # Example
///
/// With memoized state:
/// ```rust
/// struct State {}
///
/// fn Example((cx, props): Component<State>) -> DomTree {
/// // ...
/// }
/// ```
///
/// With borrowed state:
/// ```rust
/// struct State<'a> {
/// name: &'a str
/// }
///
/// fn Example<'a>((cx, props): Component<'a, State>) -> DomTree<'a> {
/// // ...
/// }
/// ```
///
/// With owned state as a closure:
/// ```rust
/// static Example: FC<()> = |(cx, props)| {
/// // ...
/// };
/// ```
///
pub type Component<'a, T> = (Context<'a>, &'a T);
/// Create inline fragments using Component syntax.
///
/// Fragments capture a series of children without rendering extra nodes.
@ -29,7 +63,7 @@ use crate::innerlude::{Context, DomTree, LazyNodes, FC};
/// You want to use this free-function when your fragment needs a key and simply returning multiple nodes from rsx! won't cut it.
///
#[allow(non_upper_case_globals, non_snake_case)]
pub fn Fragment<'a>(cx: Context<'a>, _: &'a ()) -> DomTree<'a> {
pub fn Fragment((cx, _): Component<()>) -> DomTree {
cx.render(LazyNodes::new(|f| f.fragment_from_iter(cx.children())))
}

View file

@ -69,7 +69,7 @@ impl<'src> Context<'src> {
/// ## Example
///
/// ```rust
/// const App: FC<()> = |cx, props|{
/// const App: FC<()> = |(cx, props)|{
/// cx.render(rsx!{
/// CustomCard {
/// h1 {}
@ -78,7 +78,7 @@ impl<'src> Context<'src> {
/// })
/// }
///
/// const CustomCard: FC<()> = |cx, props|{
/// const CustomCard: FC<()> = |(cx, props)|{
/// cx.render(rsx!{
/// div {
/// h1 {"Title card"}
@ -181,12 +181,12 @@ impl<'src> Context<'src> {
/// ```
/// struct SharedState(&'static str);
///
/// static App: FC<()> = |cx, props|{
/// static App: FC<()> = |(cx, props)|{
/// cx.provide_state(SharedState("world"));
/// rsx!(cx, Child {})
/// }
///
/// static Child: FC<()> = |cx, props|{
/// static Child: FC<()> = |(cx, props)|{
/// let state = cx.consume_state::<SharedState>();
/// rsx!(cx, div { "hello {state.0}" })
/// }
@ -221,7 +221,7 @@ impl<'src> Context<'src> {
/// # Example
///
/// ```rust
/// static App: FC<()> = |cx, props| {
/// static App: FC<()> = |(cx, props)| {
/// todo!();
/// rsx!(cx, div { "Subtree {id}"})
/// };
@ -238,7 +238,7 @@ impl<'src> Context<'src> {
/// # Example
///
/// ```rust
/// static App: FC<()> = |cx, props| {
/// static App: FC<()> = |(cx, props)| {
/// let id = cx.get_current_subtree();
/// rsx!(cx, div { "Subtree {id}"})
/// };

View file

@ -18,7 +18,7 @@ use std::{any::Any, cell::RefCell, future::Future, ops::Deref, rc::Rc};
/// Returns the handle to the task and the value (if it is ready, else None).
///
/// ```
/// static Example: FC<()> = |cx, props| {
/// static Example: FC<()> = |(cx, props)| {
/// let (task, value) = use_task(|| async {
/// timer::sleep(Duration::from_secs(1)).await;
/// "Hello World"

View file

@ -57,7 +57,7 @@ pub(crate) mod innerlude {
pub use crate::virtual_dom::*;
pub type DomTree<'a> = Option<VNode<'a>>;
pub type FC<P> = for<'a> fn(Context<'a>, &'a P) -> DomTree<'a>;
pub type FC<P> = for<'a> fn(Component<'a, P>) -> DomTree<'a>;
}
pub use crate::innerlude::{
@ -67,7 +67,7 @@ pub use crate::innerlude::{
};
pub mod prelude {
pub use crate::component::{fc_to_builder, Fragment, Properties};
pub use crate::component::{fc_to_builder, Component, Fragment, Properties};
pub use crate::context::Context;
pub use crate::hooks::*;
pub use crate::innerlude::{DioxusElement, DomTree, LazyNodes, Mutations, NodeFactory, FC};

View file

@ -526,7 +526,7 @@ impl<'a> NodeFactory<'a> {
let caller: &'a mut dyn for<'b> Fn(&'b Scope) -> DomTree<'b> =
bump.alloc(move |scope: &Scope| -> DomTree {
let props: &'_ P = unsafe { &*(raw_props as *const P) };
let res = component(Context { scope }, props);
let res = component((Context { scope }, props));
unsafe { std::mem::transmute(res) }
});

View file

@ -60,7 +60,7 @@ impl Scope {
///
/// # Example
/// ```rust
/// let mut dom = VirtualDom::new(|cx, props|cx.render(rsx!{ div {} }));
/// let mut dom = VirtualDom::new(|(cx, props)|cx.render(rsx!{ div {} }));
/// dom.rebuild();
///
/// let base = dom.base_scope();
@ -82,7 +82,7 @@ impl Scope {
/// # Example
///
/// ```rust
/// let mut dom = VirtualDom::new(|cx, props|cx.render(rsx!{ div {} }));
/// let mut dom = VirtualDom::new(|(cx, props)|cx.render(rsx!{ div {} }));
/// dom.rebuild();
///
/// let base = dom.base_scope();
@ -110,7 +110,7 @@ impl Scope {
/// # Example
///
/// ```rust
/// let mut dom = VirtualDom::new(|cx, props|cx.render(rsx!{ div {} }));
/// let mut dom = VirtualDom::new(|(cx, props)|cx.render(rsx!{ div {} }));
/// dom.rebuild();
///
/// let base = dom.base_scope();
@ -130,7 +130,7 @@ impl Scope {
/// # Example
///
/// ```rust
/// let mut dom = VirtualDom::new(|cx, props|cx.render(rsx!{ div {} }));
/// let mut dom = VirtualDom::new(|(cx, props)|cx.render(rsx!{ div {} }));
/// dom.rebuild();
///
/// let base = dom.base_scope();
@ -148,7 +148,7 @@ impl Scope {
/// # Example
///
/// ```rust
/// let mut dom = VirtualDom::new(|cx, props|cx.render(rsx!{ div {} }));
/// let mut dom = VirtualDom::new(|(cx, props)|cx.render(rsx!{ div {} }));
/// dom.rebuild();
/// let base = dom.base_scope();
///

View file

@ -33,7 +33,7 @@ use std::{any::Any, rc::Rc};
///
/// Example
/// ```rust
/// static App: FC<()> = |cx, props|{
/// static App: FC<()> = |(cx, props)|{
/// cx.render(rsx!{
/// div {
/// "Hello World"
@ -145,7 +145,7 @@ impl VirtualDom {
// Safety: this callback is only valid for the lifetime of the root props
let root_caller: Rc<dyn Fn(&Scope) -> DomTree> = Rc::new(move |scope: &Scope| unsafe {
let props = _p.downcast_ref::<P>().unwrap();
std::mem::transmute(root(Context { scope }, props))
std::mem::transmute(root((Context { scope }, props)))
});
let scheduler = Scheduler::new(sender, receiver);
@ -196,7 +196,7 @@ impl VirtualDom {
/// struct AppProps {
/// route: &'static str
/// }
/// static App: FC<AppProps> = |cx, props|cx.render(rsx!{ "route is {cx.route}" });
/// static App: FC<AppProps> = |(cx, props)|cx.render(rsx!{ "route is {cx.route}" });
///
/// let mut dom = VirtualDom::new_with_props(App, AppProps { route: "start" });
///
@ -222,7 +222,7 @@ impl VirtualDom {
let root_caller: Box<dyn Fn(&Scope) -> DomTree> =
Box::new(move |scope: &Scope| unsafe {
let props: &'_ P = &*(props_ptr as *const P);
std::mem::transmute(root(Context { scope }, props))
std::mem::transmute(root((Context { scope }, props)))
});
root_scope.update_scope_dependencies(&root_caller, ScopeChildren(&[]));
@ -246,7 +246,7 @@ impl VirtualDom {
///
/// # Example
/// ```
/// static App: FC<()> = |cx, props|cx.render(rsx!{ "hello world" });
/// static App: FC<()> = |(cx, props)|cx.render(rsx!{ "hello world" });
/// let mut dom = VirtualDom::new();
/// let edits = dom.rebuild();
///
@ -271,7 +271,7 @@ impl VirtualDom {
/// value: Shared<&'static str>,
/// }
///
/// static App: FC<AppProps> = |cx, props|{
/// static App: FC<AppProps> = |(cx, props)|{
/// let val = cx.value.borrow();
/// cx.render(rsx! { div { "{val}" } })
/// };
@ -333,7 +333,7 @@ impl VirtualDom {
/// # Example
///
/// ```no_run
/// static App: FC<()> = |cx, props|rsx!(cx, div {"hello"} );
/// static App: FC<()> = |(cx, props)|rsx!(cx, div {"hello"} );
/// let mut dom = VirtualDom::new(App);
/// loop {
/// let deadline = TimeoutFuture::from_ms(16);

View file

@ -3,7 +3,7 @@ use dioxus_core as dioxus;
use dioxus_core_macro::*;
use dioxus_html as dioxus_elements;
static Parent: FC<()> = |cx, props| {
static Parent: FC<()> = |(cx, props)| {
let value = cx.use_hook(|_| String::new(), |f| &*f, |_| {});
cx.render(rsx! {
@ -21,7 +21,7 @@ struct ChildProps<'a> {
name: &'a String,
}
fn Child<'a>(cx: Context<'a>, props: &'a ChildProps) -> DomTree<'a> {
fn Child<'a>((cx, props): Component<'a, ChildProps>) -> DomTree<'a> {
cx.render(rsx! {
div {
h1 { "it's nested" }
@ -35,7 +35,7 @@ struct Grandchild<'a> {
name: &'a String,
}
fn Child2<'a>(cx: Context<'a>, props: &Grandchild) -> DomTree<'a> {
fn Child2<'a>((cx, props): Component<'a, Grandchild>) -> DomTree<'a> {
cx.render(rsx! {
div { "Hello {props.name}!" }
})

View file

@ -19,7 +19,7 @@ fn new_dom<P: 'static + Send>(app: FC<P>, props: P) -> VirtualDom {
#[test]
fn test_original_diff() {
static APP: FC<()> = |cx, props| {
static APP: FC<()> = |(cx, props)| {
cx.render(rsx! {
div {
div {
@ -55,7 +55,7 @@ fn test_original_diff() {
#[test]
fn create() {
static APP: FC<()> = |cx, props| {
static APP: FC<()> = |(cx, props)| {
cx.render(rsx! {
div {
div {
@ -118,7 +118,7 @@ fn create() {
#[test]
fn create_list() {
static APP: FC<()> = |cx, props| {
static APP: FC<()> = |(cx, props)| {
cx.render(rsx! {
{(0..3).map(|f| rsx!{ div {
"hello"
@ -167,7 +167,7 @@ fn create_list() {
#[test]
fn create_simple() {
static APP: FC<()> = |cx, props| {
static APP: FC<()> = |(cx, props)| {
cx.render(rsx! {
div {}
div {}
@ -205,7 +205,7 @@ fn create_simple() {
}
#[test]
fn create_components() {
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
cx.render(rsx! {
Child { "abc1" }
Child { "abc2" }
@ -213,7 +213,7 @@ fn create_components() {
})
};
static Child: FC<()> = |cx, props| {
static Child: FC<()> = |(cx, props)| {
cx.render(rsx! {
h1 {}
div { {cx.children()} }
@ -266,7 +266,7 @@ fn create_components() {
}
#[test]
fn anchors() {
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
cx.render(rsx! {
{true.then(|| rsx!{ div { "hello" } })}
{false.then(|| rsx!{ div { "goodbye" } })}
@ -295,13 +295,13 @@ fn anchors() {
#[test]
fn suspended() {
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
let val = use_suspense(
cx,
|| async {
//
},
|cx, _| cx.render(rsx! { "hi "}),
|cx, p| cx.render(rsx! { "hi "}),
);
cx.render(rsx! { {val} })
};

View file

@ -16,7 +16,7 @@ const IS_LOGGING_ENABLED: bool = true;
#[test]
fn please_work() {
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
cx.render(rsx! {
div {
hidden: "true"
@ -30,7 +30,7 @@ fn please_work() {
})
};
static Child: FC<()> = |cx, props| {
static Child: FC<()> = |(cx, props)| {
cx.render(rsx! {
div { "child" }
})

View file

@ -8,7 +8,7 @@ use dioxus_html as dioxus_elements;
#[async_std::test]
async fn event_queue_works() {
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
cx.render(rsx! {
div { "hello world" }
})

View file

@ -10,7 +10,7 @@ type Shared<T> = Rc<RefCell<T>>;
#[test]
fn sample_refs() {
// static App: FC<()> = |cx, props|{
// static App: FC<()> = |(cx, props)|{
// let div_ref = use_node_ref::<MyRef, _>(cx);
// cx.render(rsx! {

View file

@ -20,7 +20,7 @@ fn manual_diffing() {
value: Shared<&'static str>,
}
static App: FC<AppProps> = |cx, props| {
static App: FC<AppProps> = |(cx, props)| {
let val = props.value.lock().unwrap();
cx.render(rsx! { div { "{val}" } })
};

View file

@ -17,12 +17,12 @@ fn new_dom() -> TestDom {
fn shared_state_test() {
struct MySharedState(&'static str);
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
cx.provide_state(MySharedState("world!"));
rsx!(cx, Child {})
};
static Child: FC<()> = |cx, props| {
static Child: FC<()> = |(cx, props)| {
let shared = cx.consume_state::<MySharedState>()?;
rsx!(cx, "Hello, {shared.0}")
};

View file

@ -15,7 +15,7 @@ use dioxus_html as dioxus_elements;
#[test]
fn app_runs() {
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
//
cx.render(rsx!( div{"hello"} ))
};
@ -26,7 +26,7 @@ fn app_runs() {
#[test]
fn fragments_work() {
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
cx.render(rsx!(
div{"hello"}
div{"goodbye"}
@ -40,7 +40,7 @@ fn fragments_work() {
#[test]
fn lists_work() {
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
cx.render(rsx!(
h1 {"hello"}
{(0..6).map(|f| rsx!(span{ "{f}" }))}
@ -53,7 +53,7 @@ fn lists_work() {
#[test]
fn conditional_rendering() {
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
cx.render(rsx!(
h1 {"hello"}
{true.then(|| rsx!(span{ "a" }))}
@ -70,13 +70,13 @@ fn conditional_rendering() {
#[test]
fn child_components() {
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
cx.render(rsx!(
{true.then(|| rsx!(Child { }))}
{false.then(|| rsx!(Child { }))}
))
};
static Child: FC<()> = |cx, props| {
static Child: FC<()> = |(cx, props)| {
cx.render(rsx!(
h1 {"hello"}
h1 {"goodbye"}
@ -89,7 +89,7 @@ fn child_components() {
#[test]
fn suspended_works() {
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
let title = use_suspense(cx, || async { "bob" }, |cx, f| cx.render(rsx! { "{f}"}));
cx.render(rsx!("hello" { title }))
};

View file

@ -7,7 +7,7 @@ fn main() {
dioxus::desktop::launch(App, |c| c)
}
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
let (count, set_count) = use_state(cx, || 0);
cx.render(rsx!(
@ -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: FC<()> = |(cx, props)| {
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: FC<()> = |(cx, props)| {
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: FC<()> = |(cx, props)| {
cx.render(rsx!(
GlobalTray {
MenuGroup {
@ -90,7 +90,7 @@ static Tray: FC<()> = |cx, props| {
};
// using a builder
static Tray: FC<()> = |cx, props| {
static Tray: FC<()> = |(cx, props)| {
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: FC<()> = |(cx, props)| {
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: FC<()> = |(cx, props)| {
cx.render(rsx!(
MenuBarMajorItem { title: "File"
MenuGroup {

View file

@ -21,7 +21,7 @@ pub struct Client {
pub description: String,
}
static App: FC<()> = |cx, _| {
static App: FC<()> = |(cx, _)| {
let scene = use_state(cx, || Scene::ClientsList);
let clients = use_ref(cx, || vec![] as Vec<Client>);

View file

@ -8,7 +8,7 @@ fn main() {
dioxus_desktop::launch(App, |c| c);
}
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
cx.render(rsx!(
div {
"hello world!"

View file

@ -1,5 +1,6 @@
use std::cell::RefCell;
use dioxus::prelude::Component;
use dioxus_core as dioxus;
use dioxus_core::{Context, DomTree, LazyNodes, NodeFactory, Properties};
use dioxus_core_macro::Props;
@ -53,7 +54,7 @@ pub struct WebviewWindowProps<'a> {
///
///
///
pub fn WebviewWindow<'a>(cx: Context<'a>, props: &'a WebviewWindowProps) -> DomTree<'a> {
pub fn WebviewWindow<'a>((cx, props): Component<'a, WebviewWindowProps>) -> DomTree<'a> {
let dtcx = cx.consume_state::<RefCell<DesktopContext>>()?;
cx.use_hook(
@ -89,7 +90,7 @@ fn syntax_works() {
use dioxus_hooks::*;
use dioxus_html as dioxus_elements;
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
cx.render(rsx! {
// left window
WebviewWindow {

View file

@ -10,7 +10,7 @@ fn main() {}
// Remvoe,
// }
// static Component: FC<()> = |cx, props|{
// static Component: FC<()> = |(cx, props)|{
// let (tasks, dispatch) = use_reducer(
// cx,
// || CompState { tasks: Vec::new() },

View file

@ -36,7 +36,7 @@ uses the same memoization on top of the use_context API.
Here's a fully-functional todo app using the use_map API:
```rust
static TodoList: FC<()> = |cx, props|{
static TodoList: FC<()> = |(cx, props)|{
let todos = use_map(cx, || HashMap::new());
let input = use_ref(|| None);

View file

@ -35,7 +35,7 @@ use std::{
///
/// Usage:
/// ```ignore
/// const Example: FC<()> = |cx, props|{
/// const Example: FC<()> = |(cx, props)|{
/// let counter = use_state(cx, || 0);
/// let increment = |_| counter += 1;
/// let decrement = |_| counter += 1;

View file

@ -5,7 +5,7 @@ Render a Dioxus VirtualDOM to a string.
```rust
// Our app:
const App: FC<()> = |cx, props| rsx!(cx, div {"hello world!"});
const App: FC<()> = |(cx, props)| rsx!(cx, div {"hello world!"});
// Build the virtualdom from our app
let mut vdom = VirtualDOM::new(App);

View file

@ -12,7 +12,7 @@ fn main() {
)
}
pub static App: FC<()> = |cx, props| {
pub static App: FC<()> = |(cx, props)| {
cx.render(rsx!(
div {
class: "overflow-hidden"

View file

@ -42,7 +42,7 @@ fn main() {}
// initial_name: String,
// }
// static Example: FC<ExampleProps> = |cx, props| {
// static Example: FC<ExampleProps> = |(cx, props)| {
// let dispaly_name = use_state(cx, move || props.initial_name.clone());
// cx.render(rsx! {

View file

@ -24,7 +24,7 @@ fn main() {
.unwrap();
}
pub static App: FC<()> = |cx, props| {
pub static App: FC<()> = |(cx, props)| {
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: FC<()> = |(cx, props)| {
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: FC<()> = |(cx, props)| {
//
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: FC<()> = |(cx, props)| {
//
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: FC<()> = |(cx, props)| {
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: FC<()> = |(cx, props)| {
cx.render(rsx!(
svg {
fill: "none"

View file

@ -44,7 +44,7 @@ pub fn render_vdom_scope(vdom: &VirtualDom, scope: ScopeId) -> Option<String> {
///
/// ## Example
/// ```ignore
/// static App: FC<()> = |cx, props|cx.render(rsx!(div { "hello world" }));
/// static App: FC<()> = |(cx, props)|cx.render(rsx!(div { "hello world" }));
/// let mut vdom = VirtualDom::new(App);
/// vdom.rebuild();
///
@ -243,13 +243,13 @@ mod tests {
use dioxus_core_macro::*;
use dioxus_html as dioxus_elements;
static SIMPLE_APP: FC<()> = |cx, props| {
static SIMPLE_APP: FC<()> = |(cx, props)| {
cx.render(rsx!(div {
"hello world!"
}))
};
static SLIGHTLY_MORE_COMPLEX: FC<()> = |cx, props| {
static SLIGHTLY_MORE_COMPLEX: FC<()> = |(cx, props)| {
cx.render(rsx! {
div {
title: "About W3Schools"
@ -268,14 +268,14 @@ mod tests {
})
};
static NESTED_APP: FC<()> = |cx, props| {
static NESTED_APP: FC<()> = |(cx, props)| {
cx.render(rsx!(
div {
SIMPLE_APP {}
}
))
};
static FRAGMENT_APP: FC<()> = |cx, props| {
static FRAGMENT_APP: FC<()> = |(cx, props)| {
cx.render(rsx!(
div { "f1" }
div { "f2" }
@ -331,7 +331,7 @@ mod tests {
#[test]
fn styles() {
static STLYE_APP: FC<()> = |cx, props| {
static STLYE_APP: FC<()> = |(cx, props)| {
cx.render(rsx! {
div { style: { color: "blue", font_size: "46px" } }
})

View file

@ -16,7 +16,7 @@ struct DogApi {
message: String,
}
static APP: FC<()> = |cx, _props| {
static APP: FC<()> = |(cx, _props)| {
let state = use_state(cx, || 0);
const ENDPOINT: &str = "https://dog.ceo/api/breeds/image/random/";

View file

@ -14,7 +14,7 @@ fn main() {
dioxus_web::launch(APP, |c| c)
}
static APP: FC<()> = |cx, _| {
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!"));
@ -86,4 +86,4 @@ fn render_list(cx: Context, count: usize) -> DomTree {
rsx!(cx, ul { {items} })
}
static CHILD: FC<()> = |cx, _| rsx!(cx, div {"hello child"});
static CHILD: FC<()> = |(cx, _)| rsx!(cx, div {"hello child"});

View file

@ -24,7 +24,7 @@ fn main() {
dioxus_web::launch(App, |c| c)
}
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
let mut state = use_state(cx, || 0);
cx.render(rsx! {
div {

View file

@ -23,7 +23,7 @@ fn main() {
// dioxus::web::launch(App, |c| c);
}
static App: FC<()> = |cx, props| {
static App: FC<()> = |(cx, props)| {
dbg!("rednering parent");
cx.render(rsx! {
div {
@ -40,7 +40,7 @@ static App: FC<()> = |cx, props| {
})
};
static But: FC<()> = |cx, props| {
static But: FC<()> = |(cx, props)| {
let mut count = use_state(cx, || 0);
// let d = Dropper { name: "asd" };

View file

@ -28,7 +28,7 @@ pub struct Client {
pub description: String,
}
static App: FC<()> = |cx, _| {
static App: FC<()> = |(cx, _)| {
let scene = use_state(cx, || Scene::ClientsList);
let clients = use_ref(cx, || vec![] as Vec<Client>);

View file

@ -24,7 +24,7 @@ fn main() {
dioxus_web::launch(App, |c| c)
}
pub static App: FC<()> = |cx, props| {
pub static App: FC<()> = |(cx, props)| {
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: FC<()> = |(cx, props)| {
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: FC<()> = |(cx, props)| {
//
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: FC<()> = |(cx, props)| {
//
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: FC<()> = |(cx, props)| {
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: FC<()> = |(cx, props)| {
cx.render(rsx!(
svg {
fill: "none"

View file

@ -86,7 +86,7 @@ mod ric_raf;
/// dioxus_web::launch(App, |c| c);
/// }
///
/// static App: FC<()> = |cx, props| {
/// static App: FC<()> = |(cx, props)| {
/// rsx!(cx, div {"hello world"})
/// }
/// ```
@ -110,7 +110,7 @@ pub fn launch(root_component: FC<()>, configuration: impl FnOnce(WebConfig) -> W
/// name: String
/// }
///
/// static App: FC<RootProps> = |cx, props| {
/// static App: FC<RootProps> = |(cx, props)| {
/// rsx!(cx, div {"hello {props.name}"})
/// }
/// ```

View file

@ -32,7 +32,7 @@ use dioxus::prelude::*;
struct NoKeysProps {
data: std::collections::HashMap<u32, String>,
}
static AntipatternNoKeys: FC<NoKeysProps> = |cx, props| {
static AntipatternNoKeys: FC<NoKeysProps> = |(cx, props)| {
// WRONG: Make sure to add keys!
rsx!(cx, ul {
{props.data.iter().map(|(k, v)| rsx!(li { "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: FC<()> = |(cx, props)| {
// Try to avoid heavily nesting fragments
rsx!(cx,
Fragment {
@ -82,7 +82,7 @@ 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 AntipaternRelyingOnSetState: FC<()> = |cx, props| {
static AntipaternRelyingOnSetState: FC<()> = |(cx, props)| {
let (state, set_state) = use_state(cx, || "Hello world").classic();
set_state("New state");
// This will return false! `state` will *still* be "Hello world"
@ -99,7 +99,7 @@ static AntipaternRelyingOnSetState: FC<()> = |cx, props| {
/// - All components must start with an uppercase character
///
/// IE: 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: FC<()> = |(cx, props)| todo!();
/// Antipattern: Misusing hooks
/// ---------------------------
@ -120,7 +120,7 @@ static antipattern_component: FC<()> = |cx, props| todo!();
struct MisuedHooksProps {
should_render_state: bool,
}
static AntipatternMisusedHooks: FC<MisuedHooksProps> = |cx, props| {
static AntipatternMisusedHooks: FC<MisuedHooksProps> = |(cx, props)| {
if props.should_render_state {
// do not place a hook in the conditional!
// prefer to move it out of the conditional
@ -153,7 +153,7 @@ static AntipatternMisusedHooks: FC<MisuedHooksProps> = |cx, props| {
/// }
/// }
/// })
static _example: FC<()> = |cx, props| todo!();
static _example: FC<()> = |(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: FC<()> = |(cx, props)| todo!();
pub static Example: FC<()> = |cx, props| {
pub static Example: FC<()> = |(cx, props)| {
cx.render(rsx! {
AntipatternNoKeys { data: std::collections::HashMap::new() }
AntipatternNestedFragments {}

View file

@ -9,7 +9,7 @@
use dioxus::prelude::*;
pub static Example: FC<()> = |cx, props| {
pub static Example: FC<()> = |(cx, props)| {
cx.render(rsx! {
div {
Greeting {
@ -25,7 +25,7 @@ struct GreetingProps {
name: &'static str,
}
static Greeting: FC<GreetingProps> = |cx, props| {
static Greeting: FC<GreetingProps> = |(cx, props)| {
cx.render(rsx! {
div {
h1 { "Hello, {props.name}!" }

View file

@ -18,7 +18,7 @@
use dioxus::prelude::*;
pub static Example: FC<()> = |cx, props| {
pub static Example: FC<()> = |(cx, props)| {
cx.render(rsx! {
div {
Banner {
@ -31,7 +31,7 @@ pub static Example: FC<()> = |cx, props| {
})
};
pub static Banner: FC<()> = |cx, props| {
pub static Banner: FC<()> = |(cx, props)| {
cx.render(rsx! {
div {
h1 { "This is a great banner!" }

View file

@ -16,7 +16,7 @@ use dioxus::prelude::*;
pub struct MyProps {
should_show: bool,
}
pub static Example0: FC<MyProps> = |cx, props| {
pub static Example0: FC<MyProps> = |(cx, props)| {
cx.render(rsx! {
div {
{props.should_show.then(|| rsx!{
@ -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: FC<MyProps1> = |(cx, props)| {
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: FC<MyProps2> = |(cx, props)| {
cx.render(rsx! {
div {
{match props.color {
@ -89,7 +89,7 @@ pub static Example2: FC<MyProps2> = |cx, props| {
})
};
pub static Example: FC<()> = |cx, props| {
pub static Example: FC<()> = |(cx, props)| {
let should_show = use_state(cx, || false);
let mut color_index = use_state(cx, || 0);
let color = match *color_index % 2 {

View file

@ -1,7 +1,7 @@
use dioxus::prelude::*;
fn main() {}
pub static Example: FC<()> = |cx, props| {
pub static Example: FC<()> = |(cx, props)| {
cx.render(rsx! {
div {
@ -10,7 +10,7 @@ pub static Example: FC<()> = |cx, props| {
};
// A controlled component:
static ControlledSelect: FC<()> = |cx, props| {
static ControlledSelect: FC<()> = |(cx, props)| {
let value = use_state(cx, || String::from("Grapefruit"));
cx.render(rsx! {
select { value: "{value}", onchange: move |evt| value.set(evt.value()),
@ -23,7 +23,7 @@ static ControlledSelect: FC<()> = |cx, props| {
};
// TODO - how do uncontrolled things work?
static UncontrolledSelect: FC<()> = |cx, props| {
static UncontrolledSelect: FC<()> = |(cx, props)| {
let value = use_state(cx, || String::new());
cx.render(rsx! {

View file

@ -11,7 +11,7 @@
use dioxus::prelude::*;
pub static Example: FC<()> = |cx, props| {
pub static Example: FC<()> = |(cx, props)| {
cx.render(rsx! {
div {
custom_element {

View file

@ -5,4 +5,4 @@
use dioxus::prelude::*;
pub static Example: FC<()> = |cx, props| cx.render(rsx! { Fragment {} });
pub static Example: FC<()> = |(cx, props)| cx.render(rsx! { Fragment {} });

View file

@ -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: FC<()> = |(cx, props)| {
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: FC<()> = |(cx, props)| {
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: FC<()> = |(cx, props)| {
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: FC<()> = |(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 short-circuit the match-based error handling with `.ok()` which converts
/// a Result<T, V> into an Option<T> and lets you
static App4: FC<()> = |cx, props| {
static App4: FC<()> = |(cx, props)| {
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 never need to disply a screen like this. It's rather bad taste
static App5: FC<()> = |cx, props| match get_data_err() {
static App5: FC<()> = |(cx, props)| match get_data_err() {
Ok(data) => cx.render(rsx!( div { "{data}" } )),
Err(c) => cx.render(rsx!( div { "Failed to load data: {c}" } )),
};

View file

@ -11,7 +11,7 @@
use dioxus::prelude::*;
// Returning multiple elements with rsx! or html!
static App1: FC<()> = |cx, props| {
static App1: FC<()> = |(cx, props)| {
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: FC<()> = |(cx, props)| {
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: FC<()> = |(cx, props)| {
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: FC<()> = |(cx, props)| {
cx.render(rsx! {
App1 {}
App2 {}

View file

@ -19,7 +19,7 @@ h1 {color: blue;}
p {color: red;}
"#;
pub static Example: FC<()> = |cx, props| {
pub static Example: FC<()> = |(cx, props)| {
cx.render(rsx! {
head { style { "{STYLE}" } }
body {

View file

@ -10,7 +10,7 @@
use dioxus::prelude::*;
pub static Example: FC<()> = |cx, props| {
pub static Example: FC<()> = |(cx, props)| {
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 alows 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: FC<()> = |(cx, props)| {
cx.render(rsx! {
div { color: "red"
"hello world!"

View file

@ -12,7 +12,7 @@
use dioxus::prelude::*;
pub static Example: FC<()> = |cx, props| {
pub static Example: FC<()> = |(cx, props)| {
let example_data = use_state(cx, || 0);
let v = (0..10).map(|f| {

View file

@ -7,7 +7,7 @@
use dioxus::prelude::*;
pub static Example: FC<()> = |cx, props| {
pub static Example: FC<()> = |(cx, props)| {
cx.render(rsx! {
ButtonList {}
NonUpdatingEvents {}
@ -16,7 +16,7 @@ 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| {
static ButtonList: FC<()> = |(cx, props)| {
let name = use_state(cx, || "...?");
let names = ["jack", "jill", "john", "jane"]
@ -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: FC<()> = |(cx, props)| {
rsx!(cx, div {
button {
onclick: move |_| log::info!("Did not cause any updates!")
@ -42,7 +42,7 @@ static NonUpdatingEvents: FC<()> = |cx, props| {
})
};
static DisablePropogation: FC<()> = |cx, props| {
static DisablePropogation: FC<()> = |(cx, props)| {
rsx!(cx,
div {
onclick: move |_| log::info!("event propogated to the div!")

View file

@ -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: FC<()> = |(cx, props)| {
cx.render(rsx! {
div { "100% memoized!" }
})
@ -35,7 +35,7 @@ pub struct MyProps1 {
name: String,
}
pub static Example1: FC<MyProps1> = |cx, props| {
pub static Example1: FC<MyProps1> = |(cx, props)| {
cx.render(rsx! {
div { "100% memoized! {props.name}" }
})
@ -49,7 +49,7 @@ pub struct MyProps2 {
name: std::rc::Rc<str>,
}
pub static Example2: FC<MyProps2> = |cx, props| {
pub static Example2: FC<MyProps2> = |(cx, props)| {
cx.render(rsx! {
div { "100% memoized! {props.name}" }
})

View file

@ -1,7 +1,7 @@
use dioxus::prelude::*;
fn main() {}
pub static Example: FC<()> = |cx, props| {
pub static Example: FC<()> = |(cx, props)| {
let p = 10;
cx.render(rsx! {

View file

@ -1,7 +1,7 @@
use dioxus::prelude::*;
fn main() {}
pub static Example: FC<()> = |cx, props| {
pub static Example: FC<()> = |(cx, props)| {
cx.render(rsx! {
div {

View file

@ -9,7 +9,7 @@
use dioxus::prelude::*;
pub static Example: FC<()> = |cx, props| {
pub static Example: FC<()> = |(cx, props)| {
let props = MyProps {
count: 0,
live: true,

View file

@ -1,7 +1,7 @@
use dioxus::prelude::*;
fn main() {}
pub static Example: FC<()> = |cx, props| {
pub static Example: FC<()> = |(cx, props)| {
cx.render(rsx! {
div {

View file

@ -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: FC<()> = |(cx, props)| {
let doggo = use_suspense(
cx,
|| surf::get(ENDPOINT).recv_json::<DogApi>(),

View file

@ -24,7 +24,7 @@
use dioxus::prelude::*;
pub static Example: FC<()> = |cx, props| {
pub static Example: FC<()> = |(cx, props)| {
let count = use_state(cx, || 0);
let mut direction = use_state(cx, || 1);

View file

@ -1,6 +1,6 @@
use dioxus::prelude::*;
pub static Example: FC<()> = |cx, props| {
pub static Example: FC<()> = |(cx, props)| {
cx.render(rsx! {
div {

View file

@ -1,7 +1,7 @@
use dioxus::prelude::*;
use dioxus::ssr;
pub static Example: FC<()> = |cx, props| {
pub static Example: FC<()> = |(cx, props)| {
let as_string = use_state(cx, || {
// Currently, SSR is only supported for whole VirtualDOMs
// This is an easy/low hanging fruit to improve upon
@ -15,7 +15,7 @@ pub static Example: FC<()> = |cx, props| {
})
};
static SomeApp: FC<()> = |cx, props| {
static SomeApp: FC<()> = |(cx, props)| {
cx.render(rsx! {
div { style: {background_color: "blue"}
h1 {"Some amazing app or component"}

View file

@ -93,7 +93,7 @@
//! Dioxus uses hooks for state management. Hooks are a form of state persisted between calls of the function component.
//!
//! ```
//! pub pub static Example: FC<()> = |cx, props|{
//! pub pub static Example: FC<()> = |(cx, props)|{
//! let (val, set_val) = use_state(cx, || 0);
//! cx.render(rsx!(
//! button { onclick: move |_| set_val(val + 1) }
@ -156,7 +156,7 @@
//! diouxs::web::launch(Example);
//! }
//!
//! pub pub static Example: FC<()> = |cx, props|{
//! pub pub static Example: FC<()> = |(cx, props)|{
//! cx.render(rsx! {
//! div { "Hello World!" }
//! })