What it does
State in a canvas app is held in three places — global variables, screen-scoped context variables and collections — and screens are swapped with Navigate and Back. Most of the time you don't need any of it, because control properties recalculate from their inputs on their own.
Key facts
- Three variable types: global (set with
Set, app-wide scope), context (set withUpdateContextor as the third argument ofNavigate, single-screen scope), and collections (created withCollectorClearCollect, app-wide, hold a table). - Variables are never declared. They're created implicitly by appearing in
Set,UpdateContext,Navigate,CollectorClearCollect, and their type is inferred from usage. TwoSetcalls with different types is an error, whether or not either ever runs. - All variables start blank when the app opens and are lost when it closes. To persist, write to a data source with
Patch/Collect, or to the device withSaveData. SaveDataandLoadDatawork in Power Apps mobile only — not in Studio and not in the web player.- A context variable with the same name as a global variable or collection wins. Reach the global with the disambiguation operator
[@Name]. - Reserved names you must not use for variables:
ActiveScreen,DesignHeight,DesignWidth,Height,MinScreenHeight,MinScreenWidth,SizeBreakpoints,StudioVersion,TestCaseId,Testing,TestSuiteId,Theme,Width. NavigateandBackonly change what's displayed. Screens that aren't visible keep running, keep their control values, and can be referenced in formulas from other screens.App.StartScreensets the first screen and is evaluated once at load. It's a data-flow property: no behaviour functions, and global variables and collections — including anything set inOnStart— aren't available to it. Named formulas are.- Using
NavigateinOnStartis retired. Existing apps still work and there's a temporary switch under app settings (Retired), but the supported approach isStartScreen.
When to use / skip
Default to no variable at all: if a label can read its value from a control or a data source, let it. Use a context variable when the state genuinely belongs to one screen — a dialog's visibility, a selected tab. Use a global when several screens need the same value and it's small. Use a collection when you're accumulating rows the user is editing before commit, like a basket. Do not use a collection as a local copy of a data source you're only reading; that's the single most common cause of a slow canvas app.
Configuration decisions
- Which state is genuinely app-wide versus screen-local, decided before you start rather than by whichever function you typed first.
- Whether shared values become named formulas in
App.Formulasinstead of globals set inOnStart— named formulas are always current, can't be overwritten from elsewhere, and can be deferred until needed. - How you pass state between screens:
Navigate's third argument (explicit, self-documenting) or a global (convenient, untraceable). - What survives an app restart, and where it's persisted.
- A naming convention that makes scope obvious at a glance, because Power Fx won't tell you whether
varUseris global or context.
Gotchas
- Cross-screen references force other screens to load. Referencing
Screen4.Gallery1.Selectedfrom Screen 1 pulls Screen 4 into the startup path. - Variables are implicitly typed and implicitly created, so a typo doesn't error — it silently creates a second variable that is always blank.
Back()walks a navigation stack, so a "cancel" button that callsBack()can land somewhere unexpected if the user arrived by an unusual route.Navigateto a named screen when the destination matters.SetinOnStartis a timing dependency. With non-blockingOnStartbehaviour, a screen can render and become interactive beforeOnStarthas finished, so a variable it sets may still be blank when a control reads it.- Collections built with
ClearCollectblock until they finish. Anything downstream waits, including the first screen.
Consultant notes
- The strongest habit to teach a client's makers is "ask what you'd do in Excel first". Most variables in a handed-over app are there because someone reached for a variable out of habit.
- Push named formulas hard on new builds. They remove a whole class of "why is this blank on first load" defects, and they're easier for the next person to read than a hundred-line
OnStart. - Pass a correlation or record ID explicitly through
Navigaterather than leaning on globals. When you're debugging in six months you'll be able to see where state came from. - Warn the client that
SaveData/LoadDatadoesn't work in the browser. It's a common reason a demo works on a phone and fails in the showcase on a laptop.
Worth another look if OnStart behaviour changes again, or when named formulas become the default pattern in the maker templates.