You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Remove incorrect 'watches after early returns' violation
Early returns are ALWAYS safe - watches after them simply don't execute and don't participate in ordering. The problem is only conditional watches on the SAME execution path followed by other watches.
Changes:
- Removed 'Watch After Early Returns' violation section
- Updated 'Early Returns Are Always Safe' section with correct explanation
- Removed early returns from DON'T list and troubleshooting
- Added to DO list: 'Use early returns freely - they're always safe'
- Updated tip box to clarify early returns create separate execution paths
The ordering rule only matters when **subsequent watches** exist. If a watch is conditional but **no watches follow it**, there's no order disruption!
55
+
The ordering rule only matters when watches **may or may not be called on the SAME execution path**.
56
+
57
+
-**Conditional watches at the end** - safe because no watches follow
58
+
-**Early returns** - always safe because they create separate execution paths
64
59
:::
65
60
61
+
66
62
### ✅ Conditional Watches at the END
67
63
68
64
Conditional watches are **perfectly safe** when they're the last watches in your build:
@@ -91,23 +87,24 @@ class MyWidget extends WatchingWidget {
91
87
- Conditional watch is LAST - no subsequent watches to disrupt
92
88
- On rebuild: same order maintained
93
89
94
-
### ✅ Early Returns After All Watches
90
+
### ✅ Early Returns Are Always Safe
95
91
96
-
Early returns are **safe** when all watches have already been called:
92
+
Early returns don't affect watch ordering because watches after them are never called:
97
93
98
94
```dart
99
95
class MyWidget extends WatchingWidget {
100
96
@override
101
97
Widget build(BuildContext context) {
102
-
// Call ALL watches first
103
-
final data = watchValue((DataManager m) => m.data);
104
98
final isLoading = watchValue((DataManager m) => m.isLoading);
105
99
106
-
// ✅ Early return AFTER watches - safe!
100
+
// ✅ Early return - completely safe!
107
101
if (isLoading) {
108
102
return CircularProgressIndicator();
109
103
}
110
104
105
+
// This watch only executes when NOT loading
106
+
final data = watchValue((DataManager m) => m.data);
107
+
111
108
if (data.isEmpty) {
112
109
return Text('No data');
113
110
}
@@ -118,11 +115,11 @@ class MyWidget extends WatchingWidget {
118
115
```
119
116
120
117
**Why this is safe:**
121
-
-All watches execute before any early return
122
-
-Order is complete and consistent
123
-
-Return statements don't affect watch order
118
+
-Watches after early returns simply never execute
119
+
-They don't participate in the ordering mechanism
120
+
-No order disruption possible
124
121
125
-
**Key principle:** The danger is watches that may or may not be calledFOLLOWED by other watches. If your conditional/early return is at the end, there are no subsequent watches to worry about.
122
+
**Key principle:** The danger is watches that **may or may not be called** on the SAME build path FOLLOWED by other watches. Early returns create separate execution paths, so watches after them are not part of the ordering for that path.
126
123
127
124
## Safe Conditional Patterns
128
125
@@ -160,7 +157,6 @@ class MyWidget extends WatchingWidget {
160
157
**Solution:**
161
158
- Check for watches inside `if` statements **followed by other watches**
162
159
- Check for watches inside loops
163
-
- Check for watches after early returns **when other watches exist after the return**
164
160
- Move conditional watches to the END if you need them
165
161
166
162
### Unexpected Data
@@ -174,17 +170,17 @@ class MyWidget extends WatchingWidget {
174
170
## Best Practices Checklist
175
171
176
172
✅ **DO:**
177
-
- Call all watches at the top of `build()`
178
-
- Use unconditional watch calls when possible
173
+
- Call all watches at the top of `build()` when possible
174
+
- Use unconditional watch calls for watches that need to execute on all paths
179
175
- Store values in variables, use variables conditionally
180
176
- Watch the full list, iterate over values
181
-
- Use conditional watches or early returns **at the end** (after all other watches)
177
+
- Use conditional watches at the end (after all other watches)
178
+
- Use early returns freely - they're always safe
182
179
183
180
❌ **DON'T:**
184
181
- Put watches in `if` statements **when followed by other watches**
0 commit comments