vide/docs/tut/crash-course/9-derived-source.md
2023-09-28 16:39:25 +01:00

2.2 KiB

Derived Sources

We have seen the basic way to derive a source:

local count = source(0)

local text = function()
    return "count: " .. tostring(count())
end

print(text()) -- "count: 0"
count(1)
print(text()) -- "count: 1"

However, in some cases where this source could be used by multiple effects at the same time, the function wrapping the source will needlessly rerun to convert the count into a string for each effect using it.

local source = vide.source
local effect = vide.effect

local count = source(0)

local text = function()
    print "ran"
    return "count: " .. tostring(count())
end

effect(function()
    text() -- prints "ran"
end)

effect(function()
    text() -- prints "ran" again
end)

To avoid this, you can use derive() to derive a new source instead. This will run a callback in a new reactive scope only when a dependent source has updated. Reading this derived source multiple times will just return a cached result from when it last updated.

local source = vide.source
local derive = vide.derive
local effect = vide.effect

local count = source(0)

local text = derive(function()
    print "ran"
    return "count: " .. tostring(count())
end)

effect(function()
    text() -- prints "ran"
end)

effect(function()
    text() -- does not print, returns cached value
end)

derive() must also be used within a root reactive scope, just like effect().

If the recalculated value is the same as the old value, the derived source will not rerun the effects using it.

The reactive graph for the above example:

%%{init: {
    "theme": "base",
    "themeVariables": {
        "primaryColor": "#1B1B1F",
        "primaryTextColor": "#fff",
        "primaryBorderColor": "#1B1B1F",
        "lineColor": "#79B8FF",
        "tertiaryColor": "#161618",
        "tertiaryBorderColor": "#161618"
    }
}}%%

graph

subgraph root
    direction LR
    count --> text --> effect1 & effect2
end

Deriving a source in this manner is similar to creating an effect to update another source. You should never manually do this using an effect however, improper usage could accidently create infinite loops in the reactive graph. Always favour deriving when you need one source to update based on another.