Severity: AnalysisErrorSeverity.WARNING
Maturity: experimental
Since 1.0.0
DO NOT access required props when they're not guaranteed to be present, since that can cause errors and bad behavior.
Required props are only validated to be present on props a component was rendered with, and not on other props objects.
For example, given props:
mixin FooProps {
late int requiredProp;
}
example() {
final props = Foo(); // Create an empty props object.
// Throws because the map is empty, and the value `null`
// is not an `int`.
props.requiredProp;
}
DO use utility methods getRequiredProp
, getRequiredPropOrNull
, or containsProp
checks to safely access the prop.
GOOD:
renderFoo([Map? _additionalFooProps]) {
final fooProps = Foo({...?_additionalFooProps});
// Safe access via `.getRequiredProp`
final requiredProp1 = fooProps.getRequiredProp((p) => p.requiredProp1),
orElse: () => 'custom default');
// Safe access via `.getRequiredPropOrNull`
final requiredProp2Uppercase = fooProps
.getRequiredPropOrNull((p) => requiredProp2)
?.toUpperCase();
// Safe access via if-check with `.containsProp`
final otherPropsToAdd = Foo();
if (fooProps.containsProp((p) => p.requiredProp3)) {
otherPropsToAdd.aria.label = fooProps.requiredProp3;
}
// ...
}
BAD:
@override
renderFoo([Map? _additionalFooProps]) {
final fooProps = Foo({...?_additionalFooProps});
// Unsafe; `.requiredProp1` will throw if it's not present.
final requiredProp1 = fooProps.requiredProp1 ?? 'custom default';
// Unsafe; `.requiredProp1` will throw if it's not present.
// Also, there's a static analysis error because there's a null-aware
// on the non-nullable `requiredProp2`
final requiredProp2Uppercase = fooProps.requiredProp2?.toUpperCase();
// Unsafe; `.requiredProp3` will throw if it's not present.
// Also, there's a static analysis error on the condition because
// the non-nulllable requiredProp3 will always `!= null`.
final otherPropsToAdd = Foo();
if (fooProps.requiredProp3 != null) {
otherPropsToAdd.aria.label = fooProps.requiredProp3;
}
// ...
}