Browse Source

docs: update the docs

Jonathan Kelley 3 years ago
parent
commit
c0e0196a67

+ 4 - 4
docs/guide/src/README.md

@@ -2,10 +2,10 @@
 
 
 ![dioxuslogo](./images/dioxuslogo_full.png)
 ![dioxuslogo](./images/dioxuslogo_full.png)
 
 
-**Dioxus** is a framework and ecosystem for building fast, scalable, and robust user interfaces with the Rust programming language. This guide will help you get up-and-running with Dioxus running on the Web, Desktop, Mobile, and more.
+**Dioxus** is a framework and ecosystem for building fast, scalable, and robust user interfaces with the Rust programming language. This guide will help you get started with Dioxus running on the Web, Desktop, Mobile, and more.
 
 
 ```rust
 ```rust
-fn App(cx: Context, props: &()) -> Element {
+fn App(cx: Scope) -> Element {
     let mut count = use_state(&cx, || 0);
     let mut count = use_state(&cx, || 0);
 
 
     cx.render(rsx!(
     cx.render(rsx!(
@@ -18,7 +18,7 @@ fn App(cx: Context, props: &()) -> Element {
 
 
 In general, Dioxus and React share many functional similarities. If this guide is lacking in any general concept or an error message is confusing, React's documentation might be more helpful. We are dedicated to providing a *familiar* toolkit for UI in Rust, so we've chosen to follow in the footsteps of popular UI frameworks (React, Redux, etc). If you know React, then you already know Dioxus. If you don't know either, this guide will still help you!
 In general, Dioxus and React share many functional similarities. If this guide is lacking in any general concept or an error message is confusing, React's documentation might be more helpful. We are dedicated to providing a *familiar* toolkit for UI in Rust, so we've chosen to follow in the footsteps of popular UI frameworks (React, Redux, etc). If you know React, then you already know Dioxus. If you don't know either, this guide will still help you!
 
 
-> This is introduction book! For advanced topics, check out the [Reference Guide]() instead.
+> This is introduction book! For advanced topics, check out the [Reference](https://dioxuslabs.com/reference) instead.
 
 
 ## Multiplatform
 ## Multiplatform
 
 
@@ -76,7 +76,7 @@ Examples:
 - [Bluetooth scanner]()
 - [Bluetooth scanner]()
 - [Device Viewer]()
 - [Device Viewer]()
 
 
-[![FileExplorerExample](https://github.com/DioxusLabs/file-explorer-example/raw/master/image.png)](https://github.com/dioxusLabs/file-explorer/)
+[![File ExplorerExample](https://github.com/DioxusLabs/file-explorer-example/raw/master/image.png)](https://github.com/dioxusLabs/file-explorer/)
 
 
 ### Mobile Support
 ### Mobile Support
 ---
 ---

+ 3 - 3
docs/guide/src/SUMMARY.md

@@ -7,13 +7,13 @@
   - [Intro to Elements](concepts/vnodes.md)
   - [Intro to Elements](concepts/vnodes.md)
   - [Intro to Components](concepts/components.md)
   - [Intro to Components](concepts/components.md)
   - [Reusing, Importing, and Exporting Components](concepts/exporting_components.md)
   - [Reusing, Importing, and Exporting Components](concepts/exporting_components.md)
+  - [Passing children and attributes](concepts/component_children.md)
   - [Conditional Rendering](concepts/conditional_rendering.md)
   - [Conditional Rendering](concepts/conditional_rendering.md)
   - [Lists](concepts/lists.md)
   - [Lists](concepts/lists.md)
 - [Adding Interactivity](concepts/interactivity.md)
 - [Adding Interactivity](concepts/interactivity.md)
-  - [Event handlers](concepts/event_handlers.md)
   - [Hooks and Internal State](concepts/hooks.md)
   - [Hooks and Internal State](concepts/hooks.md)
-  - [Fundamental Hooks and `use_hook`](concepts/usestate.md)
-  - [User Input and Controlled Components](concepts/errorhandling.md)
+  - [Event handlers](concepts/event_handlers.md)
+  - [User Input and Controlled Components](concepts/user_input.md)
   - [Lifecycle, updates, and effects](concepts/lifecycles.md)
   - [Lifecycle, updates, and effects](concepts/lifecycles.md)
 
 
 <!-- Responding to Events
 <!-- Responding to Events

+ 3 - 3
docs/guide/src/concepts/00-index.md

@@ -49,9 +49,9 @@ let mut state = use_state(&cx, || "red");
 
 
 cx.render(rsx!(
 cx.render(rsx!(
     Container {
     Container {
-        Light { color: "red", enabled: format_args!("{}", state == "red")  }
-        Light { color: "yellow", enabled: format_args!("{}", state == "yellow") }
-        Light { color: "green", enabled: format_args!("{}", state == "green") }
+        Light { color: "red", enabled: state == "red", }
+        Light { color: "yellow", enabled: state == "yellow", }
+        Light { color: "green", enabled: state == "green", }
 
 
         onclick: move |_| {
         onclick: move |_| {
             state.set(match *state {
             state.set(match *state {

+ 1 - 1
docs/guide/src/concepts/06-subscription-api.md

@@ -20,7 +20,7 @@ some state or event occurs outside of the component. For instance, the `use_cont
 particular context.
 particular context.
 
 
 ```rust
 ```rust
-fn use_context<I>(cx: Context<T>) -> I {
+fn use_context<I>(cx: Scope<T>) -> I {
 
 
 }
 }
 
 

+ 7 - 7
docs/guide/src/concepts/10-concurrent-mode.md

@@ -5,7 +5,7 @@ Concurrent mode provides a mechanism for building efficient asynchronous compone
 To make a component asynchronous, simply change its function signature to async.
 To make a component asynchronous, simply change its function signature to async.
 
 
 ```rust
 ```rust
-fn Example(cx: Context<()>) -> Vnode {
+fn Example(cx: Scope) -> Vnode {
     rsx!{ <div> "Hello world!" </div> }
     rsx!{ <div> "Hello world!" </div> }
 }
 }
 ```
 ```
@@ -13,7 +13,7 @@ fn Example(cx: Context<()>) -> Vnode {
 becomes
 becomes
 
 
 ```rust
 ```rust
-async fn Example(cx: Context<()>) -> Vnode {
+async fn Example(cx: Scope) -> Vnode {
     rsx!{ <div> "Hello world!" </div> }
     rsx!{ <div> "Hello world!" </div> }
 }
 }
 ```
 ```
@@ -21,7 +21,7 @@ async fn Example(cx: Context<()>) -> Vnode {
 Now, logic in components can be awaited to delay updates of the component and its children. Like so:
 Now, logic in components can be awaited to delay updates of the component and its children. Like so:
 
 
 ```rust
 ```rust
-async fn Example(cx: Context<()>) -> Vnode {
+async fn Example(cx: Scope) -> Vnode {
     let name = fetch_name().await;
     let name = fetch_name().await;
     rsx!{ <div> "Hello {name}" </div> }
     rsx!{ <div> "Hello {name}" </div> }
 }
 }
@@ -40,7 +40,7 @@ Instead, we suggest using hooks and future combinators that can safely utilize t
 As part of our Dioxus hooks crate, we provide a data loader hook which pauses a component until its async dependencies are ready. This caches requests, reruns the fetch if dependencies have changed, and provides the option to render something else while the component is loading.
 As part of our Dioxus hooks crate, we provide a data loader hook which pauses a component until its async dependencies are ready. This caches requests, reruns the fetch if dependencies have changed, and provides the option to render something else while the component is loading.
 
 
 ```rust
 ```rust
-async fn ExampleLoader(cx: Context<()>) -> Vnode {
+async fn ExampleLoader(cx: Scope) -> Vnode {
     /*
     /*
     Fetch, pause the component from rendering at all.
     Fetch, pause the component from rendering at all.
 
 
@@ -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.
     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", ())
     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| rsx!{<div> "loading..." </div>})
+                                        .delayed_place_holder(1000, |cx| rsx!{ <div> "still loading..." </div>})
                                         .await;
                                         .await;
 
 
     match name {
     match name {
@@ -62,7 +62,7 @@ async fn ExampleLoader(cx: Context<()>) -> Vnode {
 ```
 ```
 
 
 ```rust
 ```rust
-async fn Example(cx: Context<()>) -> DomTree {
+async fn Example(cx: Scope) -> DomTree {
     // Diff this set between the last set
     // Diff this set between the last set
     // Check if we have any outstanding tasks?
     // Check if we have any outstanding tasks?
     //
     //

+ 7 - 5
docs/guide/src/concepts/11-arena-memo.md

@@ -21,17 +21,19 @@ fn test() -> DomTree {
     }
     }
 }
 }
 
 
-static TestComponent: Component<()> = |cx, props|html!{<div>"Hello world"</div>};
+static TestComponent: Component<()> = |cx| html!{<div>"Hello world"</div>};
 
 
-static TestComponent: Component<()> = |cx, props|{
+static TestComponent: Component<()> = |cx|{
     let g = "BLAH";
     let g = "BLAH";
     html! {
     html! {
         <div> "Hello world" </div>
         <div> "Hello world" </div>
     }
     }
 };
 };
 
 
-#[functional_component]
-static TestComponent: Component<{ name: String }> = |cx, props|html! { <div> "Hello {name}" </div> };
+#[inline_props]
+fn test_component(cx: Scope, name: String) -> Element {
+    rsx!(cx, "Hello, {name}")
+}
 ```
 ```
 
 
 ## Why this behavior?
 ## Why this behavior?
@@ -41,7 +43,7 @@ static TestComponent: Component<{ name: String }> = |cx, props|html! { <div> "He
 Take a component likes this:
 Take a component likes this:
 
 
 ```rust
 ```rust
-fn test(cx: Context<()>) -> DomTree {
+fn test(cx: Scope) -> DomTree {
     let Bundle { alpha, beta, gamma } = use_context::<SomeContext>(cx);
     let Bundle { alpha, beta, gamma } = use_context::<SomeContext>(cx);
     html! {
     html! {
         <div>
         <div>

+ 7 - 7
docs/guide/src/concepts/12-signals.md

@@ -11,7 +11,7 @@ By default, Dioxus will only try to diff subtrees of components with dynamic con
 Your component today might look something like this:
 Your component today might look something like this:
 
 
 ```rust
 ```rust
-fn Comp(cx: Context<()>) -> DomTree {
+fn Comp(cx: Scope) -> DomTree {
     let (title, set_title) = use_state(&cx, || "Title".to_string());
     let (title, set_title) = use_state(&cx, || "Title".to_string());
     cx.render(rsx!{
     cx.render(rsx!{
         input {
         input {
@@ -25,7 +25,7 @@ fn Comp(cx: Context<()>) -> DomTree {
 This component is fairly straightforward - the input updates its own value on every change. However, every call to set_title will re-render the component. If we add a large list, then every time we update the title input, Dioxus will need to diff the entire list, over, and over, and over. This is **a lot** of wasted clock-cycles!
 This component is fairly straightforward - the input updates its own value on every change. However, every call to set_title will re-render the component. If we add a large list, then every time we update the title input, Dioxus will need to diff the entire list, over, and over, and over. This is **a lot** of wasted clock-cycles!
 
 
 ```rust
 ```rust
-fn Comp(cx: Context<()>) -> DomTree {
+fn Comp(cx: Scope) -> DomTree {
     let (title, set_title) = use_state(&cx, || "Title".to_string());
     let (title, set_title) = use_state(&cx, || "Title".to_string());
     cx.render(rsx!{
     cx.render(rsx!{
         div {
         div {
@@ -48,7 +48,7 @@ Many experienced React developers will just say "this is bad design" - but we co
 We can use signals to generate a two-way binding between data and the input box. Our text input is now just a two-line component!
 We can use signals to generate a two-way binding between data and the input box. Our text input is now just a two-line component!
 
 
 ```rust
 ```rust
-fn Comp(cx: Context<()>) -> DomTree {
+fn Comp(cx: Scope) -> DomTree {
     let mut title = use_signal(&cx, || String::from("Title"));
     let mut title = use_signal(&cx, || String::from("Title"));
     cx.render(rsx!(input { value: title }))
     cx.render(rsx!(input { value: title }))
 }
 }
@@ -57,7 +57,7 @@ fn Comp(cx: Context<()>) -> DomTree {
 For a slightly more interesting example, this component calculates the sum between two numbers, but totally skips the diffing process.
 For a slightly more interesting example, this component calculates the sum between two numbers, but totally skips the diffing process.
 
 
 ```rust
 ```rust
-fn Calculator(cx: Context<()>) -> DomTree {
+fn Calculator(cx: Scope) -> DomTree {
     let mut a = use_signal(&cx, || 0);
     let mut a = use_signal(&cx, || 0);
     let mut b = use_signal(&cx, || 0);
     let mut b = use_signal(&cx, || 0);
     let mut c = a + b;
     let mut c = a + b;
@@ -96,7 +96,7 @@ Sometimes you want a signal to propagate across your app, either through far-awa
 
 
 ```rust
 ```rust
 const TITLE: Atom<String> = || "".to_string();
 const TITLE: Atom<String> = || "".to_string();
-const Provider: Component<()> = |cx, props|{
+const Provider: Component<()> = |cx|{
     let title = use_signal(&cx, &TITLE);
     let title = use_signal(&cx, &TITLE);
     rsx!(cx, input { value: title })
     rsx!(cx, input { value: title })
 };
 };
@@ -105,7 +105,7 @@ const Provider: Component<()> = |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:
 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
 ```rust
-const Receiver: Component<()> = |cx, props|{
+const Receiver: Component<()> = |cx|{
     let title = use_signal(&cx, &TITLE);
     let title = use_signal(&cx, &TITLE);
     log::info!("This will only be called once!");
     log::info!("This will only be called once!");
     rsx!(cx,
     rsx!(cx,
@@ -132,7 +132,7 @@ Dioxus automatically understands how to use your signals when mixed with iterato
 
 
 ```rust
 ```rust
 const DICT: AtomFamily<String, String> = |_| {};
 const DICT: AtomFamily<String, String> = |_| {};
-const List: Component<()> = |cx, props|{
+const List: Component<()> = |cx|{
     let dict = use_signal(&cx, &DICT);
     let dict = use_signal(&cx, &DICT);
     cx.render(rsx!(
     cx.render(rsx!(
         ul {
         ul {

+ 1 - 1
docs/guide/src/concepts/13-subtrees.md

@@ -30,7 +30,7 @@ Due to their importance in the hierarchy, Components - not nodes - are treated a
 
 
 ```rust
 ```rust
 
 
-fn Subtree<P>(cx: Context, props: P) -> DomTree {
+fn Subtree<P>(cx: Scope<P>) -> DomTree {
 
 
 }
 }
 
 

+ 217 - 0
docs/guide/src/concepts/component_children.md

@@ -0,0 +1,217 @@
+# Passing children and attributes
+
+Often times, you'll want to wrap some important functionality *around* your state, not directly nested *inside* another component. In these cases, you'll want to pass elements and attributes into a component and let the component place them appropriately.
+
+In this chapter, you'll learn about:
+- Passing elements into components
+- Passing attributes into components
+
+
+## The use case
+
+Let's say you're building a user interface and want to make some part of it clickable to another website. You would normally start with the HTML `<a>` tag, like so:
+
+```rust
+rsx!(
+    a {
+        href: "https://google.com"
+        "Link to google"
+    }
+)
+```
+
+But, what if we wanted to style our `<a>` tag? Or wrap it with some helper icon? We could abstract our RSX into its own component:
+
+
+```rust
+#[derive(Props)]
+struct ClickableProps<'a> {
+    href: &'a str,
+    title: &'a str
+}
+
+fn clickable(cx: Scope<ClickableProps>) -> Element {
+    cx.render(rsx!(
+        a {
+            href: "{cx.props.href}"
+            "{cx.props.title}"
+        }
+    ))
+}
+```
+
+And then use it in our code like so:
+
+```rust
+rsx!(
+    clickable(
+        href: "https://google.com"
+        title: "Link to Google"
+    )
+)
+```
+
+Let's say we don't just want the text to be clickable, but we want another element, like an image, to be clickable. How do we implement that?
+
+## Passing children
+
+If we want to pass an image into our component, we can just adjust our props and component to allow any `Element`.
+
+```rust
+#[derive(Props)]
+struct ClickableProps<'a> {
+    href: &'a str,
+    body: Element<'a>
+}
+
+fn clickable(cx: Scope<ClickableProps>) -> Element {
+    cx.render(rsx!(
+        a {
+            href: "{cx.props.href}"
+            {&cx.props.body}
+        }
+    ))
+}
+```
+
+Then, at the call site, we can render some nodes and pass them in:
+
+```rust
+rsx!(
+    clickable(
+        href: "https://google.com"
+        body: cx.render(rsx!(
+            img { src: "https://www.google.com/logos/doodles/2021/seasonal-holidays-2021-6753651837109324-6752733080595603-cst.gif" }
+        ))
+    )
+)
+```
+
+This pattern can become tedious in some instances, so Dioxus actually performs an implicit conversion of any `rsx` calls inside components into `Elements` at the `children` field. This means you must explicitly declare if a component can take children.
+
+```rust
+#[derive(Props)]
+struct ClickableProps<'a> {
+    href: &'a str,
+    children: Element<'a>
+}
+
+fn clickable(cx: Scope<ClickableProps>) -> Element {
+    cx.render(rsx!(
+        a {
+            href: "{cx.props.href}"
+            {&cx.props.children}
+        }
+    ))
+}
+```
+
+And to call `clickable`:
+```rust
+rsx!(
+    clickable(
+        href: "https://google.com"
+        img { src: "https://www.google.com/logos/doodles/2021/seasonal-holidays-2021-6753651837109324-6752733080595603-cst.gif" }
+    )
+)
+```
+
+> Note: Passing children into components will break any memoization due to the associated lifetime.
+
+While technically allowed, it's an antipattern to pass children more than once in a component and will probably break your app significantly.
+
+However, because the `Element` is transparently a `VNode`, we can actually match on it to extract the nodes themselves, in case we are expecting a specific format:
+
+```rust
+fn clickable(cx: Scope<ClickableProps>) -> Element {
+    match cx.props.children {
+        Some(VNode::Text(text)) => {
+            // ...
+        }
+        _ => {
+            // ...
+        }
+    }
+}
+```
+
+## Passing attributes
+
+In the cases where you need to pass arbitrary element properties into a component - say to add more functionality to the `<a>` tag, Dioxus will accept any quoted fields. This is similar to adding arbitrary fields to regular elements using quotes.
+
+```rust
+
+rsx!(
+    clickable(
+        "class": "blue-button",
+        "style": "background: red;"
+    )
+)
+
+```
+
+For a component to accept these attributes, you must add an `attributes` field to your component's properties. We can use the spread syntax to add these attributes to whatever nodes are in our component.
+
+```rust
+#[derive(Props)]
+struct ClickableProps<'a> {
+    attributes: Attributes<'a>
+}
+
+fn clickable(cx: Scope<ClickableProps>) -> Element {
+    cx.render(rsx!(
+        a { 
+            ..{cx.props.attributes},
+            "Any link, anywhere"
+        }
+    ))
+}
+```
+
+The quoted escapes are a great way to make your components more flexible.
+
+
+## Passing handlers
+
+Dioxus also provides some implicit conversions from listener attributes into an `EventHandler` for any field on components that starts with `on`. IE `onclick`, `onhover`, etc. For properties, we want to define our `on` fields as an event handler:
+
+
+```rust
+#[derive(Props)]
+struct ClickableProps<'a> {
+    onclick: EventHandler<'a, MouseEvent>
+}
+
+fn clickable(cx: Scope<ClickableProps>) -> Element {
+    cx.render(rsx!(
+        a { 
+            onclick: move |evt| cx.props.onclick.call(evt)
+        }
+    ))
+}
+```
+
+Then, we can attach a listener at the call site:
+
+```rust
+rsx!(
+    clickable(
+        onclick: move |_| log::info!("Clicked"),
+    )
+)
+```
+
+Currently, Dioxus does not support an arbitrary amount of listeners - they must be strongly typed in `Properties`. If you need this use case, you can pass in an element with these listeners, or dip down into the `NodeFactory` API.
+
+
+## Wrapping up
+
+In this chapter, we learned:
+- How to pass arbitrary nodes through the tree
+- How the `children` field works on component properties
+- How the `attributes` field works on component properties
+- How to convert `listeners` into `EventHandlers` for components
+- How to extend any node with custom attributes and children
+
+Next chapter, we'll talk about conditionally rendering parts of your user interface.
+

+ 15 - 15
docs/guide/src/concepts/components.md

@@ -84,22 +84,22 @@ struct PostProps {
 
 
 And our render function:
 And our render function:
 ```rust
 ```rust
-fn Post(cx: Context, props: &PostProps) -> Element {
+fn Post(cx: Scope<PostProps>) -> Element {
     cx.render(rsx!{
     cx.render(rsx!{
         div { class: "post-container"
         div { class: "post-container"
             VoteButton {
             VoteButton {
-                score: props.score,
+                score: cx.props.score,
             }
             }
             TitleCard {
             TitleCard {
-                title: props.title,
-                url: props.url,
+                title: cx.props.title,
+                url: cx.props.url,
             }
             }
             MetaCard {
             MetaCard {
-                original_poster: props.original_poster,
-                post_time: props.post_time,
+                original_poster: cx.props.original_poster,
+                post_time: cx.props.post_time,
             }
             }
             ActionCard {
             ActionCard {
-                post_id: props.id
+                post_id: cx.props.id
             }
             }
         }
         }
     })
     })
@@ -110,7 +110,7 @@ When declaring a component in `rsx!`, we can pass in properties using the tradit
 
 
 Let's take a look at the `VoteButton` component. For now, we won't include any interactivity - just the rendering the score and buttons to the screen.
 Let's take a look at the `VoteButton` component. For now, we won't include any interactivity - just the rendering the score and buttons to the screen.
 
 
-Most of your Components will look exactly like this: a Props struct and a render function. Every component must take a tuple of `Context` and `&Props` and return an `Element`.
+Most of your Components will look exactly like this: a Props struct and a render function. Every component must take a tuple of `Scope` and `&Props` and return an `Element`.
 
 
 As covered before, we'll build our User Interface with the `rsx!` macro and HTML tags. However, with components, we must actually "render" our HTML markup. Calling `cx.render` converts our "lazy" `rsx!` structure into an `Element`. 
 As covered before, we'll build our User Interface with the `rsx!` macro and HTML tags. However, with components, we must actually "render" our HTML markup. Calling `cx.render` converts our "lazy" `rsx!` structure into an `Element`. 
 
 
@@ -120,7 +120,7 @@ struct VoteButtonProps {
     score: i32
     score: i32
 }
 }
 
 
-fn VoteButton(cx: Context, props: &VoteButtonProps) -> Element {
+fn VoteButton(cx: Scope<VoteButtonProps>) -> Element {
     cx.render(rsx!{
     cx.render(rsx!{
         div { class: "votebutton"
         div { class: "votebutton"
             div { class: "arrow up" }
             div { class: "arrow up" }
@@ -145,7 +145,7 @@ struct TitleCardProps<'a> {
     title: &'a str,
     title: &'a str,
 }
 }
 
 
-fn TitleCard(cx: Context, props: &TitleCardProps) -> Element {
+fn TitleCard(cx: Scope<TitleCardProps>) -> Element {
     cx.render(rsx!{
     cx.render(rsx!{
         h1 { "{cx.props.title}" }
         h1 { "{cx.props.title}" }
     })
     })
@@ -156,9 +156,9 @@ For users of React: Dioxus knows *not* to memoize components that borrow propert
 
 
 This means that during the render process, a newer version of `TitleCardProps` will never be compared with a previous version, saving some clock cycles.
 This means that during the render process, a newer version of `TitleCardProps` will never be compared with a previous version, saving some clock cycles.
 
 
-## The `Context` object
+## The `Scope` object
 
 
-Though very similar to React, Dioxus is different in a few ways. Most notably, React components will not have a `Context` parameter in the component declaration. 
+Though very similar to React, Dioxus is different in a few ways. Most notably, React components will not have a `Scope` parameter in the component declaration. 
 
 
 Have you ever wondered how the `useState()` call works in React without a `this` object to actually store the state? 
 Have you ever wondered how the `useState()` call works in React without a `this` object to actually store the state? 
 
 
@@ -171,10 +171,10 @@ function Component(props) {
 ```
 ```
 
 
 
 
-Because Dioxus needs to work with the rules of Rust it uses the `Context` object to maintain some internal bookkeeping. That's what the `Context` object is: a place for the component to store state, manage listeners, and allocate elements. Advanced users of Dioxus will want to learn how to properly leverage the `Context` object to build robust and performant extensions for Dioxus.
+Because Dioxus needs to work with the rules of Rust it uses the `Scope` object to maintain some internal bookkeeping. That's what the `Scope` object is: a place for the component to store state, manage listeners, and allocate elements. Advanced users of Dioxus will want to learn how to properly leverage the `Scope` object to build robust and performant extensions for Dioxus.
 
 
 ```rust
 ```rust
-fn Post(cx: Context, props: &PostProps) -> Element {
+fn Post(cx: Scope<PostProps>) -> Element {
     cx.render(rsx!("hello"))
     cx.render(rsx!("hello"))
 }
 }
 ```
 ```
@@ -186,6 +186,6 @@ For more references on components, make sure to check out:
 
 
 - [Components in depth]()
 - [Components in depth]()
 - [Lifecycles]()
 - [Lifecycles]()
-- [The Context object]()
+- [The Scope object]()
 - [Optional Prop fields]()
 - [Optional Prop fields]()
 
 

+ 6 - 6
docs/guide/src/concepts/conditional_rendering.md

@@ -26,7 +26,7 @@ struct AppProps {
 Now that we have a "logged_in" flag accessible in our props, we can render two different screens:
 Now that we have a "logged_in" flag accessible in our props, we can render two different screens:
 
 
 ```rust
 ```rust
-fn App(cx: Context, props: &AppProps) -> Element {
+fn App(cx: Scope<AppProps>) -> Element {
     if props.logged_in {
     if props.logged_in {
         cx.render(rsx!{
         cx.render(rsx!{
             DashboardScreen {}
             DashboardScreen {}
@@ -48,7 +48,7 @@ Rust provides us algebraic datatypes: enums that can contain values. Using the `
 For instance, we could run a function that returns a Result:
 For instance, we could run a function that returns a Result:
 
 
 ```rust
 ```rust
-fn App(cx: Context, props: &())-> Element {
+fn App(cx: Scope)-> Element {
     match get_name() {
     match get_name() {
         Ok(name) => cx.render(rsx!( "Hello, {name}!" )),
         Ok(name) => cx.render(rsx!( "Hello, {name}!" )),
         Err(err) => cx.render(rsx!( "Sorry, I don't know your name, because an error occurred: {err}" )),
         Err(err) => cx.render(rsx!( "Sorry, I don't know your name, because an error occurred: {err}" )),
@@ -58,7 +58,7 @@ fn App(cx: Context, props: &())-> Element {
 
 
 We can even match against values:
 We can even match against values:
 ```rust
 ```rust
-fn App(cx: Context, props: &())-> Element {
+fn App(cx: Scope)-> Element {
     match get_name() {
     match get_name() {
         "jack" => cx.render(rsx!( "Hey Jack, how's Diane?" )),
         "jack" => cx.render(rsx!( "Hey Jack, how's Diane?" )),
         "diane" => cx.render(rsx!( "Hey Diana, how's Jack?" )),
         "diane" => cx.render(rsx!( "Hey Diana, how's Jack?" )),
@@ -72,7 +72,7 @@ Do note: the `rsx!` macro returns a `Closure`, an anonymous function that has a
 To make patterns like these less verbose, the `rsx!` macro accepts an optional first argument on which it will call `render`. Our previous component can be shortened with this alternative syntax:
 To make patterns like these less verbose, the `rsx!` macro accepts an optional first argument on which it will call `render`. Our previous component can be shortened with this alternative syntax:
 
 
 ```rust
 ```rust
-fn App(cx: Context, props: &())-> Element {
+fn App(cx: Scope)-> Element {
     match get_name() {
     match get_name() {
         "jack" => rsx!(cx, "Hey Jack, how's Diane?" ),
         "jack" => rsx!(cx, "Hey Jack, how's Diane?" ),
         "diane" => rsx!(cx, "Hey Diana, how's Jack?" ),
         "diane" => rsx!(cx, "Hey Diana, how's Jack?" ),
@@ -83,13 +83,13 @@ fn App(cx: Context, props: &())-> Element {
 
 
 This syntax even enables us to write a one-line component:
 This syntax even enables us to write a one-line component:
 ```rust
 ```rust
-static App: Component<()> = |cx, props| rsx!(cx, "hello world!");
+static App: Component<()> = |cx| 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`:
 Alternatively, for match statements, we can just return the builder itself and pass it into a final, single call to `cx.render`:
 
 
 ```rust
 ```rust
-fn App(cx: Context, props: &())-> Element {
+fn App(cx: Scope)-> Element {
     let greeting = match get_name() {
     let greeting = match get_name() {
         "jack" => rsx!("Hey Jack, how's Diane?" ),
         "jack" => rsx!("Hey Jack, how's Diane?" ),
         "diane" => rsx!("Hey Diana, how's Jack?" ),
         "diane" => rsx!("Hey Diana, how's Jack?" ),

+ 1 - 1
docs/guide/src/concepts/event_handlers.md

@@ -1,4 +1,4 @@
-# Event handlers
+# Handling Events
 
 
 In the overview for this section, we mentioned how we can modify the state of our component by responding to user-generated events inside of event listeners.
 In the overview for this section, we mentioned how we can modify the state of our component by responding to user-generated events inside of event listeners.
 
 

+ 187 - 0
docs/guide/src/concepts/hooks.md

@@ -1 +1,188 @@
 # Hooks and Internal State
 # Hooks and Internal State
+ 
+In the [Adding Interactivity](./interactivity.md) section, we briefly covered the concept of hooks and state stored internal to components.
+
+In this section, we'll dive a bit deeper into hooks, exploring both the theory and mechanics.
+
+
+
+## Theory of Hooks
+
+Over the past several decades, computer scientists and engineers have long sought the "right way" of designing user interfaces. With each new programming language, novel features are unlocked that change the paradigm in which user interfaces are coded.
+
+Generally, a number of patterns have emerged, each with their own strengths and tradeoffs. 
+
+Broadly, there are two types of GUI structures:
+
+- Immediate GUIs: re-render the entire screen on every update
+- Retained GUIs: only re-render the portion of the screen that changed
+
+Typically, immediate-mode GUIs are simpler to write but can slow down as more features, like styling, are added.
+
+Many GUIs today - including Dioxus - are written in *Retained mode* - your code changes the data of the user interface but the renderer is responsible for actually drawing to the screen. In these cases, our GUI's state sticks around as the UI is rendered.
+
+Dioxus, following in the footsteps of React, provides a "Reactive" model for you to design your UI. This model emphasizes one-way data flow and encapsulation. Essentially, your UI code should be as predictable as possible.
+
+## Mechanics of Hooks
+In order to have state stick around between renders, Dioxus provides the `hook` through the `use_hook` API. This gives us a mutable reference to data returned from the initialization function.
+
+```rust
+fn example(cx: Scope) -> Element {
+    let name: &mut String = cx.use_hook(|| "John Doe".to_string(), |hook| hook);
+
+    //
+}
+```
+
+We can even modify this value directly from an event handler:
+
+```rust
+fn example(cx: Scope) -> Element {
+    let name: &mut String = cx.use_hook(|| "John Doe".to_string(), |hook| hook);
+
+    cx.render(rsx!(
+        button {
+            onclick: move |_| name.push_str(".."),
+        }
+    ))
+}
+```
+
+Mechanically, each call to `use_hook` provides us with `&mut T` for a new value. 
+
+```rust
+fn example(cx: Scope) -> Element {
+    let name: &mut String = cx.use_hook(|| "John Doe".to_string(), |hook| hook);
+    let age: &mut u32 = cx.use_hook(|| 10, |hook| hook);
+    let friends: &mut Vec<String> = cx.use_hook(|| vec!["Jane Doe".to_string()], |hook| hook);
+
+    //
+}
+```
+
+Internally, Dioxus is creating a list of hook values with each call to `use_hook` advancing the index of the list to return the next value.
+
+Our internal HookList would look something like:
+
+```rust
+[
+    Hook<String>,
+    Hook<u32>,
+    Hook<String>,
+]
+```
+
+This is why hooks called out of order will fail - if we try to downcast a `Hook<String>` to `Hook<u32>`, Dioxus has no choice but to panic. We do provide a `try_use_hook` but you should never need that in practice.
+
+This pattern might seem strange at first, but it can be a significant upgrade over structs as blobs of state, which tend to be difficult to use in [Rust given the ownership system](https://rust-lang.github.io/rfcs/2229-capture-disjoint-fields.html).
+
+## Building new Hooks
+
+However, most hooks you'll interact with *don't* return an `&mut T` since this is not very useful in a real-world situation.
+
+Consider when we try to pass our `&mut String` into two different handlers:
+
+```rust
+fn example(cx: Scope) -> Element {
+    let name: &mut String = cx.use_hook(|| "John Doe".to_string(), |hook| hook);
+
+    cx.render(rsx!(
+        button { onclick: move |_| name.push_str("yes"), }
+        button { onclick: move |_| name.push_str("no"), }
+    ))
+}
+```
+
+Rust will not allow this to compile! We cannot `Copy` unique mutable references - they are, by definition, unique. However, we *can* reborrow our `&mut T` as an `&T` which are non-unique references and share those between handlers:
+
+```rust
+fn example(cx: Scope) -> Element {
+    let name: &String = &*cx.use_hook(|| "John Doe".to_string());
+
+    cx.render(rsx!(
+        button { onclick: move |_| log::info!("{}", name), }
+        button { onclick: move |_| log::info!("{}", name), }
+    ))
+}
+```
+
+So, for any custom hook we want to design, we need to enable mutation through [interior mutability](https://doc.rust-lang.org/book/ch15-05-interior-mutability.html) - IE move to runtime [borrow checking](https://doc.rust-lang.org/1.8.0/book/references-and-borrowing.html). We might incur a tiny runtime cost for each time we grab a new value from the hook, but this cost is extremely minimal.
+
+This example uses the `Cell` type to let us replace the value through interior mutability. `Cell` has practically zero overhead, but is slightly more limited that its `RefCell` cousin.
+
+```rust
+fn example(cx: Scope) -> Element {
+    let name: &Cell<&'static str> = cx.use_hook(|| "John Doe", |hook| hook);
+
+    cx.render(rsx!(
+        button { onclick: move |_| name.set("John"), }
+        button { onclick: move |_| name.set("Jane"), }
+    ))
+}
+```
+
+## Driving state updates through hooks
+
+Hooks like `use_state` and `use_ref` wrap this runtime borrow checking in a type that *does* implement `Copy`. Additionally, they also mark the component as "dirty" whenever a new value has been set. This way, whenever `use_state` has a new value `set`, the component knows to update.
+
+```rust
+fn example(cx: Scope) -> Element {
+    let name = use_state(&cx, || "Jack");
+
+    cx.render(rsx!(
+        "Hello, {name}"
+        button { onclick: move |_| name.set("John"), }
+        button { onclick: move |_| name.set("Jane"), }
+    ))
+}
+```
+
+Internally, our `set` function looks something like this:
+
+```rust
+impl<'a, T> UseState<'a, T> {
+    fn set(&self, new: T) {
+        // Replace the value in the cell
+        self.value.set(new);
+
+        // Mark our component as dirty
+        self.cx.needs_update();
+    }
+}
+```
+
+Most hooks we provide implement `Deref` on their values since they are essentially smart pointers. To access the underlying value, you'll often need to use the deref operator:
+
+```rust
+fn example(cx: Scope) -> Element {
+    let name = use_state(&cx, || "Jack");
+
+    match *name {
+        "Jack" => {}
+        "Jill" => {}
+        _ => {}
+    }
+
+    // ..
+}
+
+```
+
+## Hooks provided by the `Dioxus-Hooks` package
+
+By default, we bundle a handful of hooks in the Dioxus-Hooks package. Feel free to click on each hook to view its definition and associated documentation.
+
+- [use_state](https://docs.rs/dioxus_hooks/use_state) - store state with ergonomic updates
+- [use_ref](https://docs.rs/dioxus_hooks/use_ref) - store non-clone state with a refcell
+- [use_future](https://docs.rs/dioxus_hooks/use_future) - store a future to be polled after initialization
+- [use_coroutine](https://docs.rs/dioxus_hooks/use_coroutine) - store a future that can be stopped/started/communicated with
+- [use_noderef](https://docs.rs/dioxus_hooks/use_noderef) - store a handle to the native element
+- [use_callback](https://docs.rs/dioxus_hooks/use_callback) - store a callback that implements PartialEq for memoization
+- [use_provide_context](https://docs.rs/dioxus_hooks/use_provide_context) - expose state to descendent components
+- [use_context](https://docs.rs/dioxus_hooks/use_context) - consume state provided by `use_provide_context`
+  
+## Wrapping up
+
+In this chapter, we learned about the mechanics and intricacies of storing state inside a component.
+
+In the next chapter, we'll cover event listeners in similar depth, and how to combine the two to build interactive components.

+ 18 - 15
docs/guide/src/concepts/interactivity.md

@@ -35,10 +35,10 @@ fn main() {
 When Dioxus renders your app, it will pass an immutable reference of `PostProps` to your `Post` component. Here, you can pass the state down into children.
 When Dioxus renders your app, it will pass an immutable reference of `PostProps` to your `Post` component. Here, you can pass the state down into children.
 
 
 ```rust
 ```rust
-fn App(cx: Context, props: &PostProps) -> Element {
+fn App(cx: Scope<PostProps>) -> Element {
     cx.render(rsx!{
     cx.render(rsx!{
-        Title { title: &props.title }
-        Score { score: &props.score }
+        Title { title: &cx.props.title }
+        Score { score: &cx.props.score }
         // etc
         // etc
     })
     })
 }
 }
@@ -63,7 +63,7 @@ Instead, you'll want to store state internally in your components and let *that*
 The most common hook you'll use for storing state is `use_state`. `use_state` provides a slot for some data that allows you to read and update the value without accidentally mutating it.
 The most common hook you'll use for storing state is `use_state`. `use_state` provides a slot for some data that allows you to read and update the value without accidentally mutating it.
 
 
 ```rust
 ```rust
-fn App(cx: Context, props: &())-> Element {
+fn App(cx: Scope)-> Element {
     let post = use_state(&cx, || {
     let post = use_state(&cx, || {
         PostData {
         PostData {
             id: Uuid::new_v4(),
             id: Uuid::new_v4(),
@@ -111,7 +111,7 @@ When responding to user-triggered events, we'll want to "listen" for an event on
 For example, let's say we provide a button to generate a new post. Whenever the user clicks the button, they get a new post. To achieve this functionality, we'll want to attach a function to the `on_click` method of `button`. Whenever the button is clicked, our function will run, and we'll get new Post data to work with.
 For example, let's say we provide a button to generate a new post. Whenever the user clicks the button, they get a new post. To achieve this functionality, we'll want to attach a function to the `on_click` method of `button`. Whenever the button is clicked, our function will run, and we'll get new Post data to work with.
 
 
 ```rust
 ```rust
-fn App(cx: Context, props: &())-> Element {
+fn App(cx: Scope)-> Element {
     let post = use_state(&cx, || PostData::new());
     let post = use_state(&cx, || PostData::new());
 
 
     cx.render(rsx!{
     cx.render(rsx!{
@@ -128,24 +128,27 @@ We'll dive much deeper into event listeners later.
 
 
 ### Updating state asynchronously
 ### Updating state asynchronously
 
 
-We can also update our state outside of event listeners with `tasks`. `Tasks` are asynchronous blocks of our component that have the ability to cleanly interact with values, hooks, and other data in the component. `Tasks` are one-shot - if they don't complete before the component is updated by another `.set` call, then they won't finish.
+We can also update our state outside of event listeners with `coroutines`. `Coroutines` are asynchronous blocks of our component that have the ability to cleanly interact with values, hooks, and other data in the component. Since coroutines stick around between renders, the data in them must be valid for the `'static` lifetime. We must explicitly declare which values our task will rely on to avoid the `stale props` problem common in React.
 
 
 We can use tasks in our components to build a tiny stopwatch that ticks every second.
 We can use tasks in our components to build a tiny stopwatch that ticks every second.
 
 
-```rust
+> Note: The `use_future` hook will start our coroutine immediately. The `use_coroutine` hook provides more flexibility over starting and stopping futures on the fly.
 
 
-fn App(cx: Context, props: &())-> Element {
+```rust
+fn App(cx: Scope)-> 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;
-        sec_elapsed += 1;
+    use_future(&cx, || {
+        let mut sec_elapsed = sec_elapsed.to_owned();
+        async move {
+            loop {
+                TimeoutFuture::from_ms(1000).await;
+                sec_elapsed += 1;
+            }
+        }
     });
     });
 
 
-    cx.render(rsx!{
-        div { "Current stopwatch time: {sec_elapsed}" }
-    })
-
+    rsx!(cx, div { "Current stopwatch time: {sec_elapsed}" })
 }
 }
 ```
 ```
 
 

+ 2 - 2
docs/guide/src/concepts/lists.md

@@ -74,9 +74,9 @@ struct PostListProps<'a> {
 Next, we're going to define our component:
 Next, we're going to define our component:
 
 
 ```rust
 ```rust
-fn App(cx: Context, props: &PostList) -> Element {
+fn App(cx: Scope<PostList?) -> Element {
     // First, we create a new iterator by mapping the post array
     // First, we create a new iterator by mapping the post array
-    let posts = props.posts.iter().map(|post| rsx!{
+    let posts = cx.props.posts.iter().map(|post| rsx!{
         Post {
         Post {
             title: post.title,
             title: post.title,
             age: post.age,
             age: post.age,

+ 2 - 2
docs/guide/src/concepts/rsx_in_depth.md

@@ -138,7 +138,7 @@ However, with lists, Dioxus does not exactly know how to determine which element
 In these cases, it is vitally important to specify a "key" alongside the element. Keys should be persistent between renders.
 In these cases, it is vitally important to specify a "key" alongside the element. Keys should be persistent between renders.
 
 
 ```rust
 ```rust
-fn render_list(cx: Context, items: HashMap<String, Todo>) -> DomTree {
+fn render_list(cx: Scope, items: HashMap<String, Todo>) -> DomTree {
     rsx!(cx, ul {
     rsx!(cx, ul {
         {items.iter().map(|key, item| {
         {items.iter().map(|key, item| {
             li {
             li {
@@ -219,7 +219,7 @@ cx.render(rsx!{
             {true.and_then(|f| rsx!( h1 {"Conditional Rendering"} ))}
             {true.and_then(|f| rsx!( h1 {"Conditional Rendering"} ))}
 
 
             // Child nodes
             // Child nodes
-            {cx.children()}
+            {cx.props.children}
 
 
             // Any expression that is `IntoVNode`
             // Any expression that is `IntoVNode`
             {expr}
             {expr}

+ 1 - 0
docs/guide/src/concepts/user_input.md

@@ -0,0 +1 @@
+# User Input and Controlled Components

+ 0 - 2
docs/guide/src/concepts/vnodes.md

@@ -11,7 +11,6 @@ In this chapter, we'll cover:
 Because Dioxus is mostly used with HTML/CSS renderers, the default Element "collection" is HTML. Provided the `html` feature is not disabled, we can declare Elements using the `rsx!` macro:
 Because Dioxus is mostly used with HTML/CSS renderers, the default Element "collection" is HTML. Provided the `html` feature is not disabled, we can declare Elements using the `rsx!` macro:
 
 
 ```rust
 ```rust
-#use dioxus::prelude::*;
 rsx!(
 rsx!(
     div {}
     div {}
 )
 )
@@ -19,7 +18,6 @@ rsx!(
 As you might expect, we can render this call using Dioxus-SSR to produce valid HTML:
 As you might expect, we can render this call using Dioxus-SSR to produce valid HTML:
 
 
 ```rust
 ```rust
-#use dioxus::prelude::*;
 dioxus::ssr::render_lazy(rsx!(
 dioxus::ssr::render_lazy(rsx!(
     div {}
     div {}
 ))
 ))

+ 4 - 4
docs/guide/src/hello_world.md

@@ -95,7 +95,7 @@ fn main() {
     dioxus::desktop::launch(App);
     dioxus::desktop::launch(App);
 }
 }
 
 
-fn App(cx: Context, props: &()) -> Element {
+fn App(cx: Scope) -> Element {
     cx.render(rsx! (
     cx.render(rsx! (
         div { "Hello, world!" }
         div { "Hello, world!" }
     ))
     ))
@@ -125,17 +125,17 @@ fn main() {
 Finally, our app. Every component in Dioxus is a function that takes in `Context` and `Props` and returns an `Element`.
 Finally, our app. Every component in Dioxus is a function that takes in `Context` and `Props` and returns an `Element`.
 
 
 ```rust
 ```rust
-fn App(cx: Context, props: &()) -> Element {
+fn App(cx: Scope) -> Element {
     cx.render(rsx! {
     cx.render(rsx! {
         div { "Hello, world!" }
         div { "Hello, world!" }
     })    
     })    
 }
 }
 ```
 ```
 
 
-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.
+Writing `fn App(cx: Scope) -> 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
 ```rust
-static App: Component<()> = |cx, props| cx.render(rsx!(div { "Hello, world!" }));
+static App: Component<()> = |cx| cx.render(rsx!(div { "Hello, world!" }));
 ```
 ```
 
 
 ### What is this `Context` object?
 ### What is this `Context` object?

+ 7 - 0
docs/guide/src/misc/contributors.md

@@ -1 +1,8 @@
 # Contributors
 # Contributors
+
+All pull requests (including those made by a team member) must be approved by at least one other team member.
+Larger, more nuanced decisions about design, architecture, breaking changes, trade offs, etc are made by team consensus.
+
+Contributors to this guide:
+- [jkelleyrtp](https://github.com/jkelleyrtp)
+- [alexkirsz](https://github.com/alexkirsz)

+ 10 - 0
docs/guide/src/tutorial/index.md

@@ -11,3 +11,13 @@ So far, we've covered the basics of Dioxus. We've talked about:
 
 
 In this chapter, we'll build a real-world weather app that combines everything we've learned into a cute application that you can run locally. It'll let us monitor different locations simultaneously and periodically check for updates.
 In this chapter, we'll build a real-world weather app that combines everything we've learned into a cute application that you can run locally. It'll let us monitor different locations simultaneously and periodically check for updates.
 
 
+The app is running on the web [here]() but is also available:
+
+- as a desktop app
+- a mobile app
+- and as an API endpoint here
+
+![Weather App Image](static/weather_app.png)
+
+
+Let's get started! Head on to the next chapter where we create our app.

+ 33 - 0
docs/guide/src/tutorial/new_app.md

@@ -1 +1,34 @@
 # New app
 # New app
+
+To get started, let's create a new Rust project for our app. 
+
+```shell
+$ cargo new --bin weatherapp
+$ cd weatherapp
+```
+
+Make sure our project builds by default
+
+```shell
+$ cargo run
+
+   Compiling weatherapp v0.1.0
+    Finished dev [unoptimized + debuginfo] target(s) in 0.41s
+     Running `target/debug/weatherapp`
+Hello, world!
+```
+
+## Adding Dioxus Desktop as a dependency
+
+We can either edit our Cargo.toml directly:
+
+```toml
+[dependencies]
+dioxus = { version = "*", features = ["desktop"]}
+```
+
+or use `cargo-edit` to add it via the CLI:
+
+```shell
+$ cargo add dioxus --features desktop
+```

+ 0 - 30
packages/hooks/src/usemodel.rs

@@ -98,36 +98,6 @@ pub fn use_model_coroutine<'a, T, F: Future<Output = ()> + 'static>(
     )
     )
 }
 }
 
 
-pub struct UseModelCoroutine {}
-
-struct UseModelTaskInner {
-    task: RefCell<Option<ModelTask>>,
-}
-
-impl UseModelCoroutine {
-    pub fn start(&self) {}
-}
-
-pub struct ModelAsync<T> {
-    _p: PhantomData<T>,
-}
-impl<T> ModelAsync<T> {
-    pub fn write(&self) -> RefMut<'_, T> {
-        todo!()
-    }
-    pub fn read(&self) -> Ref<'_, T> {
-        todo!()
-    }
-}
-
-pub struct AppModels {}
-
-impl AppModels {
-    pub fn get<T: 'static>(&self) -> ModelAsync<T> {
-        unimplemented!()
-    }
-}
-
 impl<T> Copy for UseModel<'_, T> {}
 impl<T> Copy for UseModel<'_, T> {}
 impl<'a, T> Clone for UseModel<'a, T> {
 impl<'a, T> Clone for UseModel<'a, T> {
     fn clone(&self) -> Self {
     fn clone(&self) -> Self {