Skip to content

Explain why initState() is too early to depend on an inherited widget - #192727

Open
fahaddoc wants to merge 1 commit into
flutter:masterfrom
fahaddoc:fix/105705-depend-on-inherited-before-initstate
Open

fahaddoc wants to merge 1 commit into
flutter:masterfrom
fahaddoc:fix/105705-depend-on-inherited-before-initstate

Conversation

@fahaddoc

Copy link
Copy Markdown
Contributor

When dependOnInheritedWidgetOfExactType() is called before initState() has completed, the error explains the rule like this:

When an inherited widget changes, for example if the value of Theme.of() changes, its dependent widgets are rebuilt. If the dependent widget's reference to the inherited widget is in a constructor or an initState() method, then the rebuilt dependent widget will not reflect the changes in the inherited widget.

That last sentence describes something that does not happen. The dependency is registered either way, so the dependent widget is rebuilt and its build() method does see the new value. What is never updated is whatever initState() read, because the framework calls initState() once per State object and does not call it again for those rebuilds. Reading the error as written, it is easy to conclude that depending on an inherited widget in initState() breaks the rebuild itself, which is what the issue reports as confusing.

This replaces that sentence with the actual reason, and adds the same reason to State.initState's documentation, which told readers not to call dependOnInheritedWidgetOfExactType() there but not why. The ErrorHint that points at build() and didChangeDependencies() is unchanged.

After:

When an inherited widget changes, for example if the value of Theme.of() changes, its dependent widgets are rebuilt. The framework calls initState() only once per State object and does not call it again for those rebuilds, so a value that initState() reads from an inherited widget is never updated when that inherited widget changes.

The existing test for this error (initState() dependency on Inherited asserts) only checks that something was thrown, so the message itself was untested; the new test covers it. ExpectFail now forwards the caught error so a test can inspect it.

The issue also suggests splitting _StateLifecycle.created into two states so the message can distinguish "in the constructor" from "inside initState()". I left that out: it is a debug-only bookkeeping change and the summary line already names the method it happened before.

Fixes #105705

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

If this change needs to override an active code freeze, provide a comment explaining why. The code freeze workflow can be overridden by code reviewers. See pinned issues for any active code freezes with guidance.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

The error thrown when dependOnInheritedWidgetOfExactType() is called
before initState() completes said that "the rebuilt dependent widget
will not reflect the changes in the inherited widget", which is not what
happens: the widget is rebuilt and its build() method does see the new
value. What is never updated is whatever initState() read, because
initState() runs once and is not run again when a dependency changes.

State.initState's documentation already said not to use
dependOnInheritedWidgetOfExactType there, but did not say why.
@github-actions github-actions Bot added the framework flutter/packages/flutter repository. See also f: labels. label Sep 14, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the documentation and error messages in 'framework.dart' to clarify that 'initState' is called only once per 'State' object and is not re-run when an inherited widget changes, meaning values read within it are never updated. It also updates 'inherited_test.dart' to include a regression test verifying that the error message thrown when accessing an inherited widget in 'initState' correctly explains this behavior. There are no review comments, and thus no feedback is provided.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Confusing error message : dependOnInheritedElement() was called before ${state.runtimeType}.initState()

1 participant