chore: rename ctx to cx
This commit is contained in:
1 parent
23c14078bb
commit
81382e7044
99 files changed
+789
-664
No files matched your search
@@ -82,8 +82,8 @@ fn main() {
|
||||
dioxus::web::start(App)
|
||||
}
|
||||
|
||||
fn App(ctx: Context<()>) -> VNode {
|
||||
ctx.render(rsx! {
|
||||
fn App(cx: Context<()>) -> VNode {
|
||||
cx.render(rsx! {
|
||||
div { "Hello, world!" }
|
||||
})
|
||||
}
|
||||
@@ -108,8 +108,8 @@ fn main() {
|
||||
Finally, our app. Every component in Dioxus is a function that takes in a `Context` object and returns a `VNode`.
|
||||
|
||||
```rust
|
||||
fn App(ctx: Context<()>) -> VNode {
|
||||
ctx.render(rsx! {
|
||||
fn App(cx: Context<()>) -> VNode {
|
||||
cx.render(rsx! {
|
||||
div { "Hello, world!" }
|
||||
})
|
||||
};
|
||||
@@ -119,7 +119,7 @@ In React, you'll save data between renders with hooks. However, hooks rely on gl
|
||||
|
||||
Next, we're greeted with the `rsx!` macro. This lets us add a custom DSL for declaratively building the structure of our app. The semantics of this macro are similar to that of JSX and HTML, though with a familiar Rust-y interface. The `html!` macro is also available for writing components with a JSX/HTML syntax.
|
||||
|
||||
The `rsx!` macro is lazy: it does not immediately produce elements or allocates, but rather builds a closure which can be rendered with `ctx.render`.
|
||||
The `rsx!` macro is lazy: it does not immediately produce elements or allocates, but rather builds a closure which can be rendered with `cx.render`.
|
||||
|
||||
Now, let's launch our app in a development server:
|
||||
|
||||
@@ -135,7 +135,7 @@ If we wanted to golf a bit, we can shrink our hello-world even smaller:
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
dioxus::web::start(|ctx| ctx.render(diouxs::rsx!( div { "Hello, World!" } ))
|
||||
dioxus::web::start(|cx| cx.render(diouxs::rsx!( div { "Hello, World!" } ))
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ You'll want to write RSX where you can, and in a future release we'll have a too
|
||||
|
||||
```rust
|
||||
#[fc]
|
||||
fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
|
||||
ctx.render(html! {
|
||||
fn Example(cx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
|
||||
cx.render(html! {
|
||||
<div>
|
||||
<p> "Hello, {name}!" </p>
|
||||
<p> "Status: {pending}!" </p>
|
||||
@@ -33,8 +33,8 @@ It's also a bit easier on the eyes 🙂.
|
||||
|
||||
```rust
|
||||
#[fc]
|
||||
fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
|
||||
ctx.render(rsx! {
|
||||
fn Example(cx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
p {"Hello, {name}!"}
|
||||
p {"Status: {pending}!"}
|
||||
@@ -58,7 +58,7 @@ Commas are entirely optional, but might be useful to delineate between elements
|
||||
The `render` function provides an **extremely efficient** allocator for VNodes and text, so try not to use the `format!` macro in your components. Rust's default `ToString` methods pass through the global allocator, but all text in components is allocated inside a manually-managed Bump arena.
|
||||
|
||||
```rust
|
||||
static Example: FC<()> = |ctx| {
|
||||
static Example: FC<()> = |cx| {
|
||||
|
||||
let text = "example";
|
||||
|
||||
@@ -67,11 +67,11 @@ static Example: FC<()> = |ctx| {
|
||||
"hello"
|
||||
};
|
||||
|
||||
let user_name = use_read_async(ctx, USERNAME);
|
||||
let title = ctx.suspend(user_name, |user_name| rsx!{ h1 { "Welcome back, {user_name}" } });
|
||||
let user_name = use_read_async(cx, USERNAME);
|
||||
let title = cx.suspend(user_name, |user_name| rsx!{ h1 { "Welcome back, {user_name}" } });
|
||||
|
||||
|
||||
ctx.render(rsx!{
|
||||
cx.render(rsx!{
|
||||
div {
|
||||
h1 { "Example" },
|
||||
|
||||
@@ -125,9 +125,9 @@ static Example: FC<()> = |ctx| {
|
||||
// rsx! is lazy, and the underlying closures cannot have the same type
|
||||
// Rendering produces the VNode type
|
||||
{match rand::gen_range::<i32>(1..3) {
|
||||
1 => rsx!(in ctx, h1 { "big" })
|
||||
2 => rsx!(in ctx, h2 { "medium" })
|
||||
_ => rsx!(in ctx, h3 { "small" })
|
||||
1 => rsx!(in cx, h1 { "big" })
|
||||
2 => rsx!(in cx, h2 { "medium" })
|
||||
_ => rsx!(in cx, h3 { "small" })
|
||||
}}
|
||||
|
||||
// Optionals
|
||||
@@ -138,12 +138,12 @@ static Example: FC<()> = |ctx| {
|
||||
|
||||
// Child nodes
|
||||
// Returns &[VNode]
|
||||
{ctx.children()}
|
||||
{cx.children()}
|
||||
|
||||
// Duplicating nodes
|
||||
// Clones the nodes by reference, so they are literally identical
|
||||
{{
|
||||
let node = rsx!(in ctx, h1{ "TopNode" });
|
||||
let node = rsx!(in cx, h1{ "TopNode" });
|
||||
(0..10).map(|_| node.clone())
|
||||
}}
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
## Concurrency
|
||||
In Dioxus, VNodes are asynchronous and can their rendering can be paused at any time by awaiting a future. Hooks can combine this functionality with the Context and Subscription APIs to craft dynamic and efficient user experiences.
|
||||
|
||||
In Dioxus, VNodes are asynchronous and can their rendering can be paused at any time by awaiting a future. Hooks can combine this functionality with the Context and Subscription APIs to craft dynamic and efficient user experiences.
|
||||
|
||||
```rust
|
||||
fn user_data(ctx: Context<()>) -> VNode {
|
||||
fn user_data(cx: Context<()>) -> VNode {
|
||||
// Register this future as a task
|
||||
use_suspense(ctx, async {
|
||||
use_suspense(cx, async {
|
||||
// Continue on with the component as usual, waiting for data to arrive
|
||||
let Profile { name, birthday, .. } = fetch_data().await;
|
||||
html! {
|
||||
@@ -16,4 +17,5 @@ fn user_data(ctx: Context<()>) -> VNode {
|
||||
})
|
||||
}
|
||||
```
|
||||
Asynchronous components are powerful but can also be easy to misuse as they pause rendering for the component and its children. Refer to the concurrent guide for information on how to best use async components.
|
||||
|
||||
Asynchronous components are powerful but can also be easy to misuse as they pause rendering for the component and its children. Refer to the concurrent guide for information on how to best use async components.
|
||||
@@ -1,12 +1,13 @@
|
||||
## Liveview
|
||||
|
||||
With the Context, Subscription, and Asynchronous APIs, we've built Dioxus Liveview: a coupling of frontend and backend to deliver user experiences that do not require dedicated API development. Instead of building and maintaining frontend-specific API endpoints, components can directly access databases, server caches, and other services directly from the component.
|
||||
|
||||
These set of features are still experimental. Currently, we're still working on making these components more ergonomic
|
||||
|
||||
```rust
|
||||
fn live_component(ctx: &Context<()>) -> VNode {
|
||||
fn live_component(cx: &Context<()>) -> VNode {
|
||||
use_live_component(
|
||||
ctx,
|
||||
cx,
|
||||
// Rendered via the client
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
|| html! { <div> {"Loading data from server..."} </div> },
|
||||
|
||||
@@ -8,8 +8,8 @@ struct MyProps {
|
||||
name: String
|
||||
}
|
||||
|
||||
fn Example(ctx: Context<MyProps>) -> VNode {
|
||||
html! { <div> "Hello {ctx.ctx.name}!" </div> }
|
||||
fn Example(cx: Context<MyProps>) -> VNode {
|
||||
html! { <div> "Hello {cx.cx.name}!" </div> }
|
||||
}
|
||||
```
|
||||
|
||||
@@ -18,14 +18,14 @@ Here, the `Context` object is used to access hook state, create subscriptions, a
|
||||
```rust
|
||||
// A very terse component!
|
||||
#[fc]
|
||||
fn Example(ctx: Context, name: String) -> VNode {
|
||||
fn Example(cx: Context, name: String) -> VNode {
|
||||
html! { <div> "Hello {name}!" </div> }
|
||||
}
|
||||
|
||||
// or
|
||||
|
||||
#[functional_component]
|
||||
static Example: FC = |ctx, name: String| html! { <div> "Hello {name}!" </div> };
|
||||
static Example: FC = |cx, name: String| html! { <div> "Hello {name}!" </div> };
|
||||
```
|
||||
|
||||
The final output of components must be a tree of VNodes. We provide an html macro for using JSX-style syntax to write these, though, you could use any macro, DSL, templating engine, or the constructors directly.
|
||||
@@ -8,9 +8,9 @@ struct MyProps {
|
||||
name: String
|
||||
}
|
||||
|
||||
fn Example(ctx: Context<MyProps>) -> VNode {
|
||||
ctx.render(html! {
|
||||
<div> "Hello {ctx.name}!" </div>
|
||||
fn Example(cx: Context<MyProps>) -> VNode {
|
||||
cx.render(html! {
|
||||
<div> "Hello {cx.name}!" </div>
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
@@ -11,7 +11,7 @@ This macro allows allows a classic struct definition to be embedded directly int
|
||||
```rust
|
||||
// Inlines and destructure props *automatically*
|
||||
#[functional_component]
|
||||
fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
|
||||
fn Example(cx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
|
||||
html! {
|
||||
<div>
|
||||
<p> "Hello, {name}!" </p>
|
||||
@@ -32,10 +32,10 @@ struct ExampleProps {
|
||||
count: i32
|
||||
};
|
||||
|
||||
fn Example(ctx: &mut Context<ExampleProps>) -> VNode {
|
||||
fn Example(cx: &mut Context<ExampleProps>) -> VNode {
|
||||
let ExampleProps {
|
||||
name, pending, count
|
||||
} = ctx.props;
|
||||
} = cx.props;
|
||||
|
||||
rsx! {
|
||||
<div>
|
||||
|
||||
@@ -12,8 +12,8 @@ You'll want to write RSX where you can, and in a future release we'll have a too
|
||||
|
||||
```rust
|
||||
#[fc]
|
||||
fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
|
||||
ctx.render(html! {
|
||||
fn Example(cx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
|
||||
cx.render(html! {
|
||||
<div>
|
||||
<p> "Hello, {name}!" </p>
|
||||
<p> "Status: {pending}!" </p>
|
||||
@@ -33,8 +33,8 @@ It's also a bit easier on the eyes 🙂.
|
||||
|
||||
```rust
|
||||
#[fc]
|
||||
fn Example(ctx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
|
||||
ctx.render(rsx! {
|
||||
fn Example(cx: Context, name: &str, pending: bool, count: i32 ) -> VNode {
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
p {"Hello, {name}!"}
|
||||
p {"Status: {pending}!"}
|
||||
@@ -58,11 +58,11 @@ Commas are entirely optional, but might be useful to delineate between elements
|
||||
The `render` function provides an **extremely efficient** allocator for VNodes and text, so try not to use the `format!` macro in your components. Rust's default `ToString` methods pass through the global allocator, but all text in components is allocated inside a manually-managed Bump arena.
|
||||
|
||||
```rust
|
||||
static Example: FC<()> = |ctx| {
|
||||
static Example: FC<()> = |cx| {
|
||||
|
||||
let text = "example";
|
||||
|
||||
ctx.render(rsx!{
|
||||
cx.render(rsx!{
|
||||
div {
|
||||
h1 { "Example" },
|
||||
|
||||
@@ -114,9 +114,9 @@ static Example: FC<()> = |ctx| {
|
||||
// rsx! is lazy, and the underlying closures cannot have the same type
|
||||
// Rendering produces the VNode type
|
||||
{match rand::gen_range::<i32>(1..3) {
|
||||
1 => rsx!(in ctx, h1 { "big" })
|
||||
2 => rsx!(in ctx, h2 { "medium" })
|
||||
_ => rsx!(in ctx, h3 { "small" })
|
||||
1 => rsx!(in cx, h1 { "big" })
|
||||
2 => rsx!(in cx, h2 { "medium" })
|
||||
_ => rsx!(in cx, h3 { "small" })
|
||||
}}
|
||||
|
||||
// Optionals
|
||||
@@ -127,12 +127,12 @@ static Example: FC<()> = |ctx| {
|
||||
|
||||
// Child nodes
|
||||
// Returns &[VNode]
|
||||
{ctx.children()}
|
||||
{cx.children()}
|
||||
|
||||
// Duplicating nodes
|
||||
// Clones the nodes by reference, so they are literally identical
|
||||
{{
|
||||
let node = rsx!(in ctx, h1{ "TopNode" });
|
||||
let node = rsx!(in cx, h1{ "TopNode" });
|
||||
(0..10).map(|_| node.clone())
|
||||
}}
|
||||
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
|
||||
```rust
|
||||
fn Example(ctx: &mut Context<()>) -> VNode {
|
||||
let service = use_combubulator(ctx);
|
||||
fn Example(cx: &mut Context<()>) -> VNode {
|
||||
let service = use_combubulator(cx);
|
||||
let Status { name, pending, count } = service.info();
|
||||
html! {
|
||||
<div>
|
||||
html! {
|
||||
<div>
|
||||
<p> "Hello, {name}!" </p>
|
||||
<p> "Status: {pending}!" </p>
|
||||
<p> "Count {count}!" </p>
|
||||
<button onclick=|_| service.update()>
|
||||
<button onclick=|_| service.update()>
|
||||
"Refresh services"
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -1,47 +1,45 @@
|
||||
# Context API
|
||||
|
||||
|
||||
|
||||
```rust
|
||||
// Create contexts available to children
|
||||
// Only one context can be associated with any given component
|
||||
// This is known as "exposed state". Children can access this context,
|
||||
// but will not be automatically subscribed.
|
||||
fn ContextCreate(ctx: &mut Context<()>) -> VNode {
|
||||
let context = ctx.set_context(|| CustomContext::new());
|
||||
html! { <> {ctx.children()} </> }
|
||||
fn ContextCreate(cx: &mut Context<()>) -> VNode {
|
||||
let context = cx.set_context(|| CustomContext::new());
|
||||
html! { <> {cx.children()} </> }
|
||||
}
|
||||
|
||||
fn ContextRead(ctx: &mut Context<()>) -> VNode {
|
||||
fn ContextRead(cx: &mut Context<()>) -> VNode {
|
||||
// Panics if context is not available
|
||||
let some_ctx = ctx.get_context::<CustomContext>();
|
||||
let text = some_ctx.select("some_selector");
|
||||
let some_cx = cx.get_context::<CustomContext>();
|
||||
let text = some_cx.select("some_selector");
|
||||
html! { <div> "{text}" </div> }
|
||||
}
|
||||
|
||||
fn Subscription(ctx: &mut Context<()>) -> VNode {
|
||||
fn Subscription(cx: &mut Context<()>) -> VNode {
|
||||
// Open a "port" on the component for actions to trigger a re-evaluation
|
||||
let subscription = ctx.new_subscription();
|
||||
let subscription = cx.new_subscription();
|
||||
|
||||
// A looping timer - the effect is re-called on every re-evaluation
|
||||
use_async_effect(ctx, move || async {
|
||||
use_async_effect(cx, move || async {
|
||||
timer::new(2000).await;
|
||||
subscription.call();
|
||||
}, None);
|
||||
|
||||
// A one-shot timer, the deps don't change so the effect only happens once
|
||||
use_async_effect_deps(ctx, move || async {
|
||||
use_async_effect_deps(cx, move || async {
|
||||
timer::new(2000).await;
|
||||
subscription.call();
|
||||
}, ());
|
||||
}
|
||||
|
||||
// Mix subscriptions and context to make a simple Redux
|
||||
fn use_global_state<T: UserContextTrait>(ctx: &mut Context<()>) -> T {
|
||||
let some_ctx = ctx.get_context::<T>();
|
||||
let component_subscription = ctx.new_subscription();
|
||||
some_ctx.subscribe_component(component_subscription);
|
||||
some_ctx
|
||||
fn use_global_state<T: UserContextTrait>(cx: &mut Context<()>) -> T {
|
||||
let some_cx = cx.get_context::<T>();
|
||||
let component_subscription = cx.new_subscription();
|
||||
some_cx.subscribe_component(component_subscription);
|
||||
some_cx
|
||||
}
|
||||
|
||||
```
|
||||
@@ -1,11 +1,11 @@
|
||||
# Subscriptions
|
||||
# Subscriptions
|
||||
|
||||
Yew subscriptions are used to schedule update for components into the future. The `Context` object can create subscriptions:
|
||||
|
||||
```rust
|
||||
fn Component(ctx: Component<()>) -> VNode {
|
||||
let update = ctx.schedule();
|
||||
|
||||
fn Component(cx: Component<()>) -> VNode {
|
||||
let update = cx.schedule();
|
||||
|
||||
// Now, when the subscription is called, the component will be re-evaluted
|
||||
update.consume();
|
||||
}
|
||||
@@ -13,16 +13,15 @@ fn Component(ctx: Component<()>) -> VNode {
|
||||
|
||||
Whenever a component's subscription is called, the component will then re-evaluated. You can consider the input properties of
|
||||
a component to be just another form of subscription. By default, the Dioxus component system automatically diffs a component's props
|
||||
when the parent function is called, and if the props are different, the child component's subscription is called.
|
||||
when the parent function is called, and if the props are different, the child component's subscription is called.
|
||||
|
||||
The subscription API exposes this functionality allowing hooks and state management solutions the ability to update components whenever
|
||||
some state or event occurs outside of the component. For instance, the `use_context` hook uses this to subscribe components that use a
|
||||
particular context.
|
||||
|
||||
|
||||
```rust
|
||||
fn use_context<I>(ctx: Context<T>) -> I {
|
||||
|
||||
fn use_context<I>(cx: Context<T>) -> I {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +31,3 @@ fn use_context<I>(ctx: Context<T>) -> I {
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -5,14 +5,15 @@ Concurrent mode provides a mechanism for building efficient asynchronous compone
|
||||
To make a component asynchronous, simply change its function signature to async.
|
||||
|
||||
```rust
|
||||
fn Example(ctx: Context<()>) -> Vnode {
|
||||
fn Example(cx: Context<()>) -> Vnode {
|
||||
rsx!{ <div> "Hello world!" </div> }
|
||||
}
|
||||
```
|
||||
|
||||
becomes
|
||||
|
||||
```rust
|
||||
async fn Example(ctx: Context<()>) -> Vnode {
|
||||
async fn Example(cx: Context<()>) -> Vnode {
|
||||
rsx!{ <div> "Hello world!" </div> }
|
||||
}
|
||||
```
|
||||
@@ -20,7 +21,7 @@ async fn Example(ctx: Context<()>) -> Vnode {
|
||||
Now, logic in components can be awaited to delay updates of the component and its children. Like so:
|
||||
|
||||
```rust
|
||||
async fn Example(ctx: Context<()>) -> Vnode {
|
||||
async fn Example(cx: Context<()>) -> Vnode {
|
||||
let name = fetch_name().await;
|
||||
rsx!{ <div> "Hello {name}" </div> }
|
||||
}
|
||||
@@ -30,7 +31,7 @@ async fetch_name() -> String {
|
||||
}
|
||||
```
|
||||
|
||||
This component will only schedule its render once the fetch is complete. However, we *don't* recommend using async/await directly in your components.
|
||||
This component will only schedule its render once the fetch is complete. However, we _don't_ recommend using async/await directly in your components.
|
||||
|
||||
Async is a notoriously challenging yet rewarding tool for efficient tools. If not careful, locking and unlocking shared aspects of the component's context can lead to data races and panics. If a shared resource is locked while the component is awaiting, then other components can be locked or panic when trying to access the same resource. These rules are especially important when references to shared global state are accessed using the context object's lifetime. If mutable references to data captured immutably by the context are taken, then the component will panic, and cause confusion.
|
||||
|
||||
@@ -39,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.
|
||||
|
||||
```rust
|
||||
async fn ExampleLoader(ctx: Context<()>) -> Vnode {
|
||||
async fn ExampleLoader(cx: Context<()>) -> Vnode {
|
||||
/*
|
||||
Fetch, pause the component from rendering at all.
|
||||
|
||||
@@ -49,8 +50,8 @@ async fn ExampleLoader(ctx: 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(|ctx| rsx!{<div> "loading..." </div>})
|
||||
.delayed_place_holder(1000, |ctx| rsx!{ <div> "still loading..." </div>})
|
||||
.place_holder(|cx| rsx!{<div> "loading..." </div>})
|
||||
.delayed_place_holder(1000, |cx| rsx!{ <div> "still loading..." </div>})
|
||||
.await;
|
||||
|
||||
match name {
|
||||
@@ -60,14 +61,11 @@ async fn ExampleLoader(ctx: Context<()>) -> Vnode {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
```rust
|
||||
async fn Example(ctx: Context<()>) -> VNode {
|
||||
async fn Example(cx: Context<()>) -> VNode {
|
||||
// Diff this set between the last set
|
||||
// Check if we have any outstanding tasks?
|
||||
//
|
||||
//
|
||||
// Eventually, render the component into the VDOM when the future completes
|
||||
<div>
|
||||
<Example />
|
||||
@@ -79,6 +77,6 @@ async fn Example(ctx: Context<()>) -> VNode {
|
||||
<Suspense placeholder={html!{<div>"Loading"</div>}}>
|
||||
<Example />
|
||||
</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
```
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
Dioxus differs slightly from other UI virtual doms in some subtle ways due to its memory allocator.
|
||||
|
||||
One important aspect to understand is how props are passed down from parent components to children. All "components" (custom user-made UI elements) are tightly allocated together in an arena. However, because props and hooks are generically typed, they are casted to any and allocated on the heap - not in the arena with the components.
|
||||
One important aspect to understand is how props are passed down from parent components to children. All "components" (custom user-made UI elements) are tightly allocated together in an arena. However, because props and hooks are generically typed, they are casted to any and allocated on the heap - not in the arena with the components.
|
||||
|
||||
With this system, we try to be more efficient when leaving the component arena and entering the heap. By default, props are memoized between renders using COW and context. This makes props comparisons fast - done via ptr comparisons on the cow pointer. Because memoization is done by default, parent re-renders will *not* cascade to children if the child's props did not change.
|
||||
With this system, we try to be more efficient when leaving the component arena and entering the heap. By default, props are memoized between renders using COW and context. This makes props comparisons fast - done via ptr comparisons on the cow pointer. Because memoization is done by default, parent re-renders will _not_ cascade to children if the child's props did not change.
|
||||
|
||||
https://dmitripavlutin.com/use-react-memo-wisely/
|
||||
|
||||
This behavior is defined as an implicit attribute to user components. When in React land you might wrap a component is `react.memo`, Dioxus components are automatically memoized via an implicit attribute. You can manually configure this behavior on any component with "nomemo" to disable memoization.
|
||||
This behavior is defined as an implicit attribute to user components. When in React land you might wrap a component is `react.memo`, Dioxus components are automatically memoized via an implicit attribute. You can manually configure this behavior on any component with "nomemo" to disable memoization.
|
||||
|
||||
```rust
|
||||
fn test() -> VNode {
|
||||
@@ -21,9 +21,9 @@ fn test() -> VNode {
|
||||
}
|
||||
}
|
||||
|
||||
static TestComponent: FC<()> = |ctx| html!{<div>"Hello world"</div>};
|
||||
static TestComponent: FC<()> = |cx| html!{<div>"Hello world"</div>};
|
||||
|
||||
static TestComponent: FC<()> = |ctx| {
|
||||
static TestComponent: FC<()> = |cx| {
|
||||
let g = "BLAH";
|
||||
html! {
|
||||
<div> "Hello world" </div>
|
||||
@@ -31,7 +31,7 @@ static TestComponent: FC<()> = |ctx| {
|
||||
};
|
||||
|
||||
#[functional_component]
|
||||
static TestComponent: FC<{ name: String }> = |ctx| html! { <div> "Hello {name}" </div> };
|
||||
static TestComponent: FC<{ name: String }> = |cx| html! { <div> "Hello {name}" </div> };
|
||||
```
|
||||
|
||||
## Why this behavior?
|
||||
@@ -41,8 +41,8 @@ static TestComponent: FC<{ name: String }> = |ctx| html! { <div> "Hello {name}"
|
||||
Take a component likes this:
|
||||
|
||||
```rust
|
||||
fn test(ctx: Context<()>) -> VNode {
|
||||
let Bundle { alpha, beta, gamma } = use_context::<SomeContext>(ctx);
|
||||
fn test(cx: Context<()>) -> VNode {
|
||||
let Bundle { alpha, beta, gamma } = use_context::<SomeContext>(cx);
|
||||
html! {
|
||||
<div>
|
||||
<Component name=alpha />
|
||||
@@ -53,4 +53,4 @@ fn test(ctx: Context<()>) -> VNode {
|
||||
}
|
||||
```
|
||||
|
||||
While the contents of the destructued bundle might change, not every child component will need to be re-rendered.
|
||||
While the contents of the destructued bundle might change, not every child component will need to be re-rendered.
|
||||
Reference in new issue
Block a user