Values
Values are the cornerstone of reactivity in Flux. They are the most basic unit of reactive state, a node that holds a piece of data and notifies the graph whenever that data changes.
If you are coming from other reactive frameworks, you can think of Values as signals or atoms.
Creating a Value
Call the main Flux function with an initial value. Any non-function argument creates a Value node.
local Flux = require(ReplicatedStorage.Flux)
local count = Flux(0)
local name = Flux("Roblox")
local isVisible = Flux(true)Reading a Value
Call the node with no arguments to read its current value. Reading a node inside a reactive context (a Computed or Effect body, or a function passed to a property binding) automatically registers it as a dependency.
local count = Flux(5)
print(count:get()) --> 5
print(count()) --> 5 (shorthand for :get())Operator Overloading
Values overload the full set of Luau arithmetic and comparison operators, so you can use them transparently in expressions; no need to call () at every use site.
local count = Flux(5)
print(count * 2) --> 10
print(count + 10) --> 15
print(count > 3) --> true
print(-count) --> -5
print(count .. "x") --> "5x"These overloads call :get() under the hood, so they also register the node as a reactive dependency when evaluated inside a computation.
Updating a Value
Call the node with a new value to set it. This immediately updates the stored state and notifies any downstream observers.
local count = Flux(0)
count:set(5) -- set to 5
count(10) -- set to 10 (shorthand for :set())
count(count + 1) -- arithmetic reads the current value via __add, then sets the resultBinding to the UI
You can pass a Value (or any reactive node) directly to a property in Flux.new or Flux.edit. Flux detects the node and binds to it, and the property updates automatically whenever the node changes.
local Flux = require(ReplicatedStorage.Flux)
local new = Flux.new
local count = Flux(0)
local button = new "TextButton" {
Size = UDim2.fromOffset(200, 50),
-- Direct node binding: the Text property mirrors count automatically
Text = count,
Activated = function()
count(count + 1)
end,
}For derived values you only need in one place, you can also pass an inline function. Flux wraps it in an implicit computation:
local button = new "TextButton" {
-- Inline function: Flux creates an implicit memo for this binding
Text = function()
return "Count: " .. count
end,
}Under the Hood
When Flux sees a reactive node or a function assigned to a property, it establishes a reactive subscription. During the first evaluation, Flux observes which nodes were accessed and maps the property as a dependent of those nodes.
Whenever count(newValue) is called, Flux propagates the change through the graph, ensuring your UI stays in sync without any manual .Changed or GetPropertyChangedSignal connections.