Your custom widget renders in Run Mode, then stops responding when the page changes a value, or you can't work out how to get a result back out of it. Before you touch anything else, open the widget's code and check whether it copies a parameter into its own state field. That one check explains most of the "not updating" reports.
A FlutterFlow custom widget has to satisfy a contract before it has to look like anything. I've built more than forty custom widgets across eight FlutterFlow Marketplace templates, and the contract has three edges: what comes in, what the widget is allowed to remember, and how it speaks back. Everything below is grounded in FlutterFlow's documentation, Flutter's API docs and public issue-tracker entries. I haven't re-run the tracker cases myself for this post, so read them as reported.
What parameters can a FlutterFlow custom widget take?
A custom widget takes typed parameters that you declare in the builder and read in code as widget.parameterName, plus Widget Builder slots and Action callbacks, and it must always be given a width and a height.
FlutterFlow's custom widget documentation says "For custom widgets, it is mandatory to specify both width and height," and describes parameters as reachable through widget. in your code. That indirection matters, because widget.parameterName is a live read of the current configuration, while anything you copy out of it is a snapshot.
Two parameter kinds behave differently from plain values:
- Widget Builder. FlutterFlow's widget builder documentation describes these as parameters that "allow component authors to substitute dynamic content within the widget tree of the component." You receive a slot rather than a value, which is how you write a list widget that doesn't dictate what a row looks like.
- Action. A callback. The page hands your widget a piece of behaviour and your Dart decides when to fire it.
Something like a controller, an open stream or a Dart function you wrote elsewhere has no obvious place in the parameter panel. My recommendation is to treat the parameter list as the widget's public API: design it so everything the widget needs is expressible there, and accept that anything else has to reach it through app state. That trade-off, and the price of the dependencies underneath, is the same one described in when pub packages break inside FlutterFlow's build.
Why does a FlutterFlow custom widget stop updating?
The most common cause is a widget that copied a parameter into its own state inside initState, which Flutter calls exactly once per State object, so later parameter changes never reach the build method.
That is standard Flutter, not a FlutterFlow quirk. Flutter's initState documentation says "The framework will call this method exactly once for each State object it creates." When the parent rebuilds with a new value, didUpdateWidget is the hook the framework calls, "with the previous widget as an argument." A minimal fix looks like this:
@override
void didUpdateWidget(covariant MyWidget oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.value != widget.value) {
_controller.value = widget.value;
}
}
Or skip the local copy and read widget.value directly in build. As a rule of thumb, a widget that owns something with a lifecycle, such as a countdown timer's ticker, needs local state, while a QR generator that only renders its input doesn't. That is my recommendation, not a platform rule.
If didUpdateWidget doesn't help, the cause may sit above your code, and FlutterFlow's own tracker shows the ambiguity. Issue #2703, opened on 11 April 2024, reported that a custom widget didn't refresh after an update page state or app state action, and it is labelled "closed: not a bug". Issue #2788, opened 12 days later, describes a parameter change not reflected in a cloned documentation example, and it was still open with the label "status: confirmed" when I checked on 30 September 2026.
This suggests that "my custom widget doesn't update" is one symptom with at least two causes, and the platform's own triage has treated similar reports differently. Check didUpdateWidget first, because that fix is yours and takes a few lines. Reading app state directly through FFAppState() inside the widget is another route, but it ties the widget to the project it was written for.
A short triage order, which is my recommendation and not FlutterFlow's:
- Add a print statement inside
didUpdateWidgetand change the value from the page. If it never prints, the page isn't handing the widget a new value, and the bug lives in the page-side state or action. - If it prints but the screen stays the same, compare
oldWidgetandwidgetand confirm your build method reads the current one rather than a stale field. - If both look right, rebuild the smallest version of the widget in a fresh project and see whether it reproduces. A clean repro is what the tracker entries above are missing.
How does a FlutterFlow custom widget send a value back to the page?
It sends the value through a parameter of type Action: the widget calls the callback from Dart, and the page reads what was passed under Callback Parameters.
FlutterFlow's callbacks documentation states "To create a component that will execute a callback, you must create a component with a parameter with the Action type," and that "You can access the value passed to the callback by navigating to the Set Variable menu > Callback Parameters." The custom widgets page shows the same pattern with an onRating callback. The wiring, in order:
- Declare a parameter of type Action on the widget and give it the arguments the page will care about, for example a circular slider handing back a double.
- Call it in your Dart where the event actually happens, not inside
build. - On the page, bind an action flow to that callback the way you would to a button tap.
- Read the value through Set Variable, under Callback Parameters, rather than through a page-state variable the widget wrote to.
Step four keeps the widget portable. A widget that writes to FFAppState decides on behalf of every future user where its output lives, while a widget that fires a callback decides nothing, which is the right amount.
Does a custom widget own the screen?
No. Flutter's layout rule is "Constraints go down. Sizes go up. Parent sets position.", and Flutter's constraints guide adds that a widget can decide its own size only within the constraints its parent gives it. FlutterFlow makes that concrete by requiring width and height. Issue #2215, opened in January 2024, asked for custom widgets that size themselves to their content and was closed as "not a bug". Build for the box you're given, and use LayoutBuilder inside it for anything responsive.
Drop-in widget or full-app template?
The case study I keep for the marketplace work treats these as different products on purpose, and the architecture differs accordingly.
| Drop-in widget | Full-app template | |
|---|---|---|
| Buyer already has | An existing project with its backend chosen | An idea and a deadline |
| Where state lives | Passed in and handed back; the widget owns none of it | Page and app state the template defines |
| What a parameter means | The entire public API | An internal detail the buyer may rename |
| Likely failure | Stops updating inside someone else's layout | Screens too coupled to reuse individually |
| What ships alongside | Instructions and a reference doc | Instructions, reference docs, marketplace images, iOS screenshots, cover, thumbnail |
Dream Home and Schedule are full-app templates; the other bundles are collections of widgets. The failure-mode row is my inference from that split, not a measured result.
What changed in April 2026?
FlutterFlow v6.6.56 was released on 21 April 2026, and its release notes introduce Child Slots as "named 'drop zones' inside your components". That is about components, not custom widgets, so it doesn't change what your Dart receives. It does suggest where the platform expects reusable building blocks to be composed, which is worth knowing before you design a widget's parameter list around values alone.
If a widget still misbehaves after these checks, the question shifts to whether it belongs in FlutterFlow at all, and when to drop out of FlutterFlow into pure Flutter covers that decision. The Flutter tools I keep installed are the shorter list.
So open the last custom widget you wrote and find its initState. Does it copy widget.something into a field with no didUpdateWidget beneath it?



