persistedState
persistedState declares a cell that survives the player closing the game.
It is for preferences.
persistedState(initial: Int, key: string): StateRef<Int>persistedState(initial: String, key: string): StateRef<String>Reference
Section titled “Reference”persistedState(initial, key)
Section titled “persistedState(initial, key)”Call it at the top level of a file, never inside a component. Read it with
useState.
const roofRemoval = persistedState(1, 'docs.settings.roofs');const shiftClickDrop = persistedState(0, 'docs.settings.shift-drop');const dataOrbs = persistedState(1, 'docs.settings.orbs');const levelUpMessages = persistedState(0, 'docs.settings.levelups');Parameters
Section titled “Parameters”initial: AnIntor aString. The value on a device that has never saved one.key: A string. The durable identity of this setting in the player’s saved file.
Returns
Section titled “Returns”A declaration to pass to useState.
Caveats
Section titled “Caveats”- Renaming the variable is safe; changing the key declares a new setting and orphans the old value on every device that has one.
- Two declarations cannot share a key (
TS2E126). - Keys are tracked in a lockfile the project commits. Removing a declaration retires its key rather than freeing it, and the same key coming back recovers the values saved under it. See The state registry.
- Saved per device, not per account. A player who plays on two machines has two copies.
- This is for preferences, not for game data. Anything the game should know belongs to the server.
const roofs = persistedState(1, "docs.refused.setting");const orbs = persistedState(1, "docs.refused.setting"); // the same key twiceA remembered preference
Section titled “A remembered preference”const DisplaySettings = (): Component => { const [roofs, setRoofs] = useState(roofRemoval); <layer x={0} y={0} w="fill" h={ROW_H} onClick={() => { setRoofs(1 - roofs); }}> <CheckboxRow label="Remove roofs" on={roofs} /> </layer>Choosing a key
Section titled “Choosing a key”Name it for the setting, prefixed by the interface that owns it:
'docs.settings.roofs' says whose roofs.
Restoring defaults
Section titled “Restoring defaults”const restoreDefaults = (): void => { const [, setRoofs] = useState(roofRemoval); const [, setShiftDrop] = useState(shiftClickDrop); const [, setOrbs] = useState(dataOrbs); const [, setLevelUps] = useState(levelUpMessages); const [, setLevel] = useState(zoom); setRoofs(1); setShiftDrop(0); setOrbs(1); setLevelUps(0); setLevel(1);};Writing a persisted cell is how it is saved; there is no separate save.
Troubleshooting
Section titled “Troubleshooting”The build fails saying a key would change
Section titled “The build fails saying a key would change”The lockfile records every key that has ever existed, and CI refuses a build that would move one. If you meant to add a setting, commit the lockfile change along with the code. If you meant to rename a variable, rename the variable and leave the key alone.
Players lost their setting after a release
Section titled “Players lost their setting after a release”Its key changed. The old values are still on disk under the old key — restoring the key restores them.
Should this be persisted?
Section titled “Should this be persisted?”Ask what happens if it is lost. If the answer is “the player sets it again in a second”, session state is enough. Persist things a player would be annoyed to redo.