# Reactivity: Dynamic Scoping
Dynamic scoping is the act of creating and destroying new scopes in response to
source updates. Vide provides functions for some common use-cases to do this.
## show() REACTIVE
Shows a component if the source is truthy. Optionally shows a fallback component
if the source is falsey.
- **Type**
```luau
function show(source: () -> unknown, component: () -> T): () -> T?
function show(source: () -> unknown, component: () -> T, fallback: () -> U): () -> T | U
```
- **Details**
Creates a reactive scope internally to detect source updates.
The component is run in a stable scope when truthy, otherwise the stable
scope is destroyed.
Returns a source holding an instance of the currently shown component or
`nil` if no component is currently shown.
## switch() REACTIVE
Shows one of a set of components depending on a source and a mapping table.
- **Type**
```luau
function switch(source: () -> K): (map: Map V>): () -> V?
```
- **Details**
Creates a reactive scope internally to detect source updates.
When the source updates, its value is inputted into a map to get a component
constructor. This component is then run in a stable scope. The previous
stable scope is destroyed.
Returns a source holding an instance of the currently shown component or
`nil` if no component is currently shown.
- **Example**
```luau
local logged = source(false)
local button = switch(logged) {
[true] = function()
return Button { Text = "Log out", Toggle = logged }
end,
[false] = function()
return Button { Text = "Log in", Toggle = logged }
end
}
```
## indexes() REACTIVE
Shows a component for each index in a table.
- **Type**
```luau
function indexes(
source: () -> Map,
transform: (value: () -> VI, index: KI) -> VO
): Array
- **Details**
Creates a reactive scope internally to detect source updates.
When the source table updates, a component is generated for each index in
the table.
- For any added index, the `transform` function is run in a new stable
scope to produce an instance that is cached.
- For any removed index, the stable scope for that index is destroyed.
The `transform` function is called with:
1. A *source containing the index's value*.
2. The *index itself*.
Anytime an existing index's value changes, the `transform` function is not
rerun, instead, that index's corresponding source is updated with the new
value.
Returns a source holding an array of instances currently shown.
- **Example**
```luau
type Item = {
name: string,
icon: number
}
local items = source {} :: () -> Array-
local displays = indexes(items, function(item, i)
return ItemDisplay {
Name = function()
return i .. ": " .. item().name
end,
Image = function()
return "rbxassetid://" .. item().icon
end,
}
end)
```
## values() REACTIVE
Shows a component for each value in a table.
- **Type**
```luau
function values(
source: () -> Map,
transform: (value: VI, index: () -> KI) -> VO
): Array
- **Details**
Operates with the same idea as `indexes()`, but applied to values instead of
indexes.
Creates a reactive scope internally to detect source updates.
When the source table updates, a component is generated for each value in
the table.
- For any added value, the `transform` function is run in a new stable scope
to produce an instance that is cached.
- For any removed value, the stable scope for that value is destroyed.
The `transform` function is called with:
1. The *value itself*.
2. A *source containing the value's index*.
Anytime an existing value's index changes, the `transform` function is not
rerun, instead, that value's corresponding source is updated with the new
index.
Returns a source holding an array of instances currently shown.
::: warning
Having the same values appear multiple times in the input source table can
cause unexpected behavior. Strict mode has checks for this.
:::
- **Example**
```luau
type Item = {
name: string,
icon: number
}
local items = source {} :: () -> Array
-
local displays = values(items, function(item, i)
return ItemDisplay {
Name = function()
return i() .. ": " .. item.Name
end
Image = "rbxassetid://" .. item.icon,
}
end)
```
- **Extra**
When should you use `indexes()` and `values()`?
`values()` should be used when you have a fixed set of objects where the
same objects can be re-arranged in the source table. It maps a value to a
UI element.
e.g.
- List of all players.
- Inventory of items.
- Chat message history.
- Toast notifications.
`indexes()` should be used in other cases, especially when your source table
has primitive values. It maps an index to a UI element.
e.g.
- List of character or weapon stats.
In most cases, both functions will produce the same observed result.
The main difference is performance, picking the right function to use can
result in less property updates and less re-renders. One case to note is
that `values()` works nicely when animating re-ordering of instances, since
the source index can be used to animate a change in position for the UI
element.
--------------------------------------------------------------------------------