From 3d75f1cb054ec051846fb5b72dd7b2e55ef3e242 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Fri, 28 Jan 2022 16:11:04 -0500 Subject: [PATCH] docs: fix some typos --- .vscode/spellright.dict | 3 +++ docs/guide/.vscode/spellright.dict | 3 --- docs/guide/src/SUMMARY.md | 5 +++-- docs/guide/src/elements/composing.md | 18 +++++++++--------- docs/guide/src/interactivity/index.md | 13 +++++-------- 5 files changed, 20 insertions(+), 22 deletions(-) delete mode 100644 docs/guide/.vscode/spellright.dict diff --git a/.vscode/spellright.dict b/.vscode/spellright.dict index 7a5a261d7..06845ebf9 100644 --- a/.vscode/spellright.dict +++ b/.vscode/spellright.dict @@ -76,3 +76,6 @@ iter cloneable fudamental clonable +oninput +Webview +idanarye diff --git a/docs/guide/.vscode/spellright.dict b/docs/guide/.vscode/spellright.dict deleted file mode 100644 index 572d1f65c..000000000 --- a/docs/guide/.vscode/spellright.dict +++ /dev/null @@ -1,3 +0,0 @@ -oninput -Webview -idanarye diff --git a/docs/guide/src/SUMMARY.md b/docs/guide/src/SUMMARY.md index 5a8fadb96..d4990fc99 100644 --- a/docs/guide/src/SUMMARY.md +++ b/docs/guide/src/SUMMARY.md @@ -13,11 +13,11 @@ - [Properties](elements/propsmacro.md) - [Reusing, Importing, and Exporting](elements/exporting_components.md) - [Children and Attributes](elements/component_children.md) - - [Theory of Reactive Programming](elements/composing.md) + - [How Data Flows](elements/composing.md) - [Adding Interactivity](interactivity/index.md) - [Hooks and Internal State](interactivity/hooks.md) + - [UseState and UseRef](interactivity/importanthooks.md) - [Event Listeners](interactivity/event_handlers.md) - - [UseState and UseRef](interactivity/importanthooks.md) - [User Input and Controlled Components](interactivity/user_input.md) - [Lifecycle, updates, and effects](interactivity/lifecycles.md) - [Managing State](state/index.md) @@ -45,3 +45,4 @@ + diff --git a/docs/guide/src/elements/composing.md b/docs/guide/src/elements/composing.md index e6ccf189e..dcd54b18f 100644 --- a/docs/guide/src/elements/composing.md +++ b/docs/guide/src/elements/composing.md @@ -2,7 +2,7 @@ We've finally reached the point in our tutorial where we can talk about the "Theory of React." We've talked about defining a declarative view, but not about the aspects that make our code *reactive*. -Understanding the theory of reactive program is essential to making sense of Dioxus and writing effective, performant UIs. +Understanding the theory of reactive programming is essential to making sense of Dioxus and writing effective, performant UIs. In this section, we'll talk about: @@ -17,15 +17,15 @@ This section is a bit long, but worth the read. We recommend coffee, tea, and/or Dioxus is one the very few Rust libraries that provide a "Reactive Programming Model". The term "Reactive programming" is a classification of programming paradigm - much like functional or imperative programming. This is a very important distinction since it affects how we *think* about our code. -Reactive programming is programming model concerned with deriving computations from asynchronous data flow. Most reactive programs are comprised of a handful of datasources, intermediate computations, and a final result. +Reactive programming is a programming model concerned with deriving computations from asynchronous data flow. Most reactive programs are comprised of datasources, intermediate computations, and a final result. -We can consider the our rendered GUI to be the final result of reactive app and our datasources to include shared contexts and component properties. +We consider the rendered GUI to be the final result of our Dioxus apps. The datasources for our apps include local and global state. For example, the model presented in the figure below is comprised of two data sources: time and a constant. These values are passed through our computation graph to achieve a final result: `g`. ![Reactive Model](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e9/Reactive_programming_glitches.svg/440px-Reactive_programming_glitches.svg.png) -Whenever our `seconds` variable changes, then we will reevaluate the computation for `t`. Because `g` relies on `t`, then we will also reevaluate its computation too. Notice that we would've reevaluated the computation for `g` even if `t` didn't change because `seconds` is used to calculate `g`. +Whenever our `seconds` variable changes, we will then reevaluate the computation for `t`. Because `g` relies on `t`, we will also reevaluate its computation too. Notice that we would've reevaluated the computation for `g` even if `t` didn't change because `seconds` is used to calculate `g`. However, if we somehow changed our constant from `1` to `2`, then we need to reevaluate `t`. If, for whatever reason, this change did not affect the result of `t`, then we wouldn't try to reevaluate `g`. @@ -51,7 +51,7 @@ fn compute_graph(constant: i32, seconds: i32) -> bool { ## How is Dioxus Reactive? -The Dioxus VirtualDom provides us a framework for reactive programming. When we build apps with dioxus, we need to feed it our own custom datasources. This can be either initial props or some values fetched from the network. We then pass this data through our app into components through properties. +The Dioxus VirtualDom provides us a framework for reactive programming. When we build apps with dioxus, we need to provide our own datasources. This can be either initial props or some values fetched from the network. We then pass this data through our app into components through properties. If we represented the reactive graph presented above in Dioxus, it would look very similar: @@ -85,7 +85,7 @@ With this app, we've defined three components. Our top-level component provides Now, whenever the `constant` changes, our `RenderT` component will be re-rendered. However, if `seconds` doesn't change, then we don't need to re-render `RenderG` because the input is the same. If `seconds` *does* change, then both RenderG and RenderT will be reevaluated. -Dioxus is "Reactive" because it provides this framework for us. All we need to do is write our own tiny units of computations and Dioxus figures out which components need to be reevaluated automatically. +Dioxus is "Reactive" because it provides this framework for us. All we need to do is write our own tiny units of computation and Dioxus figures out which components need to be reevaluated automatically. These extra checks and algorithms add some overhead, which is why you see projects like [Sycamore](http://sycamore-rs.netlify.app) and [SolidJS](http://solidjs.com) eliminating them altogether. Dioxus is *really* fast, so we're willing to exchange the added overhead for improved developer experience. @@ -142,11 +142,11 @@ A single component will be called multiple times, modifying its own internal sta With the `provide_context` and `consume_context` methods on `Scope`, we can share values to descendants without having to pass values through component props. This has the side-effect of making our datasources less obvious from a high-level perspective, but it makes our components more modular within the same codebase. -To make app-global state easier to reason about, Dioxus makes all values provided through `provide_context` immutable. This means any library built on top of `provide_context` needs to use interior mutability to modify share global state. +To make app-global state easier to reason about, Dioxus makes all values provided through `provide_context` immutable. This means any library built on top of `provide_context` needs to use interior mutability to modify shared global state. In these cases, App-Global state needs to manually track which components need to be re-generated. -To regenerate *any* component in your app, you can get a handle the Dioxus' internal scheduler through `schedule_update_any`: +To regenerate *any* component in your app, you can get a handle to the Dioxus' internal scheduler through `schedule_update_any`: ```rust let force_render = cx.schedule_update_any(); @@ -155,7 +155,7 @@ let force_render = cx.schedule_update_any(); force_render(ScopeId(0)); ``` -## What does it mean for a component to "re-render" +## What does it mean for a component to "re-render"? In our guides, we frequently use the phrase "re-render" to describe updates to our app. You'll often hear this paired with "preventing unnecessary re-renders." But what exactly does this mean? diff --git a/docs/guide/src/interactivity/index.md b/docs/guide/src/interactivity/index.md index b71a3e73d..a1f963bd3 100644 --- a/docs/guide/src/interactivity/index.md +++ b/docs/guide/src/interactivity/index.md @@ -112,11 +112,11 @@ For example, let's say we provide a button to generate a new post. Whenever the ```rust fn App(cx: Scope)-> Element { - let post = use_state(&cx, || PostData::new()); + let (post, set_post) = use_state(&cx, || PostData::new()); cx.render(rsx!{ button { - on_click: move |_| post.set(PostData::random()) + on_click: move |_| set_post(PostData::random()) "Generate a random post" } Post { props: &post } @@ -131,7 +131,6 @@ We'll dive much deeper into event listeners later. We can also update our state outside of event listeners with `futures` and `coroutines`. - `Futures` are Rust's version of promises that can execute asynchronous work by an efficient polling system. We can submit new futures to Dioxus either through `push_future` which returns a `TaskId` or with `spawn`. -- - `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 and Futures 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. @@ -142,14 +141,14 @@ We can use tasks in our components to build a tiny stopwatch that ticks every se ```rust fn App(cx: Scope)-> Element { - let mut sec_elapsed = use_state(&cx, || 0); + let (elapsed, set_elapsed) = use_state(&cx, || 0); use_future(&cx, || { - to_owned![sec_elapsed]; // explicitly capture this hook for use in async + to_owned![set_elapsed]; // explicitly capture this hook for use in async async move { loop { TimeoutFuture::from_ms(1000).await; - sec_elapsed += 1; + set_elapsed.modify(|i| i + 1) } } }); @@ -162,8 +161,6 @@ Using asynchronous code can be difficult! This is just scratching the surface of ### How do I tell Dioxus that my state changed? -So far, we've only updated our state with `.set`. However, you might've noticed that we used `AddAssign` to increment the `sec_elapsed` value in our stopwatch example *without* calling set. This is because the `AddAssign` trait is implemented for `UseState` (the wrapper around our value returned from `use_state`). Under the hood, whenever you try to mutate our value through `UseState`, you're actually calling `.set` which informs Dioxus that _this_ component needs to be updated on the screen. - Whenever you inform Dioxus that the component needs to be updated, it will "render" your component again, storing the previous and current Elements in memory. Dioxus will automatically figure out the differences between the old and the new and generate a list of edits that the renderer needs to apply to change what's on the screen. This process is called "diffing": ![Diffing](../images/diffing.png)