This commit is contained in:
aaron 2024-06-20 17:36:25 +01:00
parent 67e87110c7
commit f2de9b0e63
25 changed files with 315 additions and 364 deletions

View file

@ -1,7 +1,6 @@
# Nested Reactive Scopes
# Nested Scopes
Nesting reactive scopes gives you finer control over the reactive graph, but
needs more work to do. The built-in control flow functions try to cover the
Nesting scopes gives you finer control over the reactive graph, but needs more work to do. The built-in control flow functions try to cover the
most common cases, but they do not cover all of them.
This tutorial will demonstrate how to implement a `show()` control flow function
@ -21,7 +20,7 @@ local function Counter()
}
end
mount(function()
root(function()
local toggled = source(true)
show(toggled, Button)
@ -57,7 +56,7 @@ Above is the reactive graph for `show()`. It creates a new effect depending on
`toggle` where anytime `toggle` is truthy, it will create a new `Counter`. The
`show` effect calls `Counter`, which creates a new reactive scope to update its
text whenever `count` changes. As per the rules of reactive scopes, a reactive
scope rerunning will destroy any reactive scope created within it. So the text
scope rerunning will destroy any scopes created within it. So the text
effect's reactive scope is destroyed whenever the show effect is rerun.
The same can be achieved without the use of `show()`:
@ -82,7 +81,10 @@ mount(function()
effect(function()
if toggled() then
local destroy = mount(Button)
local destroy = root(function(destroy)
Counter()
return destroy
end)
cleanup(destroy)
end
end)
@ -116,11 +118,14 @@ subgraph mount
end
```
This is another way to achieve the same. Here we use `mount()` within the effect
to manually create and destroy a new reactive scope whenever the effect reruns.
This is another way to achieve the same. Here we use `root()` within the effect
to manually create and destroy a new stable scope whenever the effect reruns.
Alternatively, instead of using `mount()`, a new reactive scope can be created
directly within the effect:
The reason for creating a stable scope is to prevent the effect from tracking
any sources that may be read inside the `Counter()` call. Otherwise, the effect
may be rerun needlessly and recreate the counter.
Alternatively, instead of using `root()`:
```lua
local mount = vide.mount
@ -174,7 +179,9 @@ end
```
Without the use of `untrack()`, an error would occur, since Vide does not allow
the creation of reactive scopes inside reactive scopes that are tracking. The
the creation of reactive scopes inside reactive scopes. `untrack()` creates a
stable scope inside the reactive scope, and we can create another reactive scope
inside that stable scope. The
reason for this, is because if the `Counter` component reads from a source
internally, that can cause the reactive scope calling `Counter()` to track that
source, causing unintentional reruns. As a guard against this, you are forced to
@ -184,5 +191,3 @@ The final result is the same as using the `show()` component. An effect is
created which creates the counter, which creates its own reactive scope. The
effect rerunning causes the counter's internal reactive scope to be destroyed,
making sure everything is cleaned up.