Create a Store
Centralized reactive state shared across any number of Handles.
A Store is a named, reactive data container. Any Handle that reads from a Store via useStore is automatically subscribed and will re-render whenever the store's data changes.
Fragment's store pattern is inspired by Zustand.
Define a Store
Each Store lives in its own ModuleScript inside your Stores/ folder. The builder function receives set and get, and must return the initial state table including any methods you want to expose.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Fragment = require(ReplicatedStorage.Fragment)
return Fragment.createStore("PlayerData", function(set, get)
return {
coins = 0,
level = 1,
setCoins = function(amount: number)
set({ coins = amount })
end,
addCoins = function(amount: number)
set({ coins = get().coins + amount })
end,
getData = function()
return get()
end,
}
end)set(partial) does a shallow merge into the store and re-renders all subscribed Handles. get() returns the full live store table.
Use the structured loader
When using Fragment.load({ Stores = ..., Handles = ... }), Stores are required before Handles automatically — no manual require needed.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Fragment = require(ReplicatedStorage.Fragment)
Fragment.load({
Stores = script.Parent.Stores, -- required first --
Handles = script.Parent.Handles,
})Connect a Store to a Handle
Use Fragment.useStore inside a renderer to read from the store and subscribe the Handle. The Handle re-renders automatically whenever set is called.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Fragment = require(ReplicatedStorage.Fragment)
local Handle = Fragment.newHandle("HUD", { "HUD", "StatsFrame" })
return Handle(function(element: Frame)
local store = Fragment.useStore("PlayerData")
local data = store.getData()
if not data then return end
element.Coins.Text = `🪙 {data.coins}`
element.Level.Text = `Lv. {data.level}`
end)Subscription is automatic
Calling useStore inside a renderer subscribes the Handle. You do not need to manually unsubscribe — Fragment manages this for you.
Stores are also available inside Component renderers via the handle argument:
return Component(function(element, props, handle)
local store = Fragment.useStore("PlayerData")
element.Text = `🪙 {store.getData().coins}`
end)Mutating store data from a signal
You can call store methods from anywhere — inside Connect callbacks, from other Handles, or from a service.
return Handle(function(element: Frame)
local store = Fragment.useStore("PlayerData")
Handle.Connect("AddCoins", element.DebugBtn.Activated, function()
store.addCoins(100) -- triggers re-render on all subscribed Handles --
end)
end)Integrating with external data sources
A common pattern is to populate the store when external data arrives — for example from ReplicaService or a remote event.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Fragment = require(ReplicatedStorage.Fragment)
Fragment.load({
Stores = script.Parent.Stores,
Handles = script.Parent.Handles,
})
local store = Fragment.useStore("PlayerData")
ReplicaService.ReplicaOfClassCreated("PlayerData", function(replica)
store.setCoins(replica.Data.Coins)
replica:ListenToChange({ "Coins" }, function(newValue)
store.setCoins(newValue)
end)
end)