[Fast Refresh] Remount correctly when an edit changes the component kโฆ
[Fast Refresh] Remount correctly when an edit changes the component kind (#36950)
Fixes #30659.
I'm not confident in this yet but here's what Fable said based on https://github.com/react/react/pull/32214#issuecomment-2734436781:
Editing a component from a plain function to a memo or forwardRef wrapper (or between wrapper kinds) crashed with "Component is not a function", because canPreserveStateBetween only compared hook signatures. The edit was classified as state-preserving, so createWorkInProgress swapped the wrapper object in as the type of a FunctionComponent fiber and renderWithHooks tried to call it.
Two fixes, both DEV-only:
canPreserveStateBetweenreturnsfalsewhentypeofor$$typeofdiffer. A fiber's tag is derived from the kind of its type, so state can never be preserved across a kind change; these edits must go tostaleFamilies(remount). Nested wrappers need no special handling becauseregister()creates a family per nesting level ($type/$renderids), and each level's kind is compared against its own family.The reconciler now finds and remounts wrapper fibers whose outer kind changed.
scheduleFibersWithFamiliesRecursivelypreviously resolved families only through the inner implementation (type/type.render), but a kind-changing edit is recorded only on the outer type's family, so edits likememo->functionnever reached the scanner and were silently dropped. The scanner now also checks theelementType's family, and the_debugNeedsRemountbranch inbeginWorkrebuilds the fiber fromfamily.current(the latest registered type for the fiber's identity) rather than the fiber's possibly-stale inner type.
This also fixes stale simple memo remounts recreating as plain functions, dropping the memo wrapper.
Unlike the reverted #30660 (see #32214), this does not fabricate families or guess type shapes: families are still created in exactly one place, and the same ID always resolves to the same family.
Restores the tests from #30660 and adds coverage for changing the inner type of a memo between function and forwardRef.
Co-authored-by: BIKI DAS bikid475@gmail.com
Co-authored-by: dan dan.abramov@me.com
Commit details
- Commit: eb343c7
- Parent: 12a4bae
- Files changed: 4
- Lines changed: 362 additions & 7 deletions
File tree
packages/react-reconciler/src/packages/react-refresh/src/__tests__
Diff summary
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| 136 | 136 | |
| 137 | 137 | |
| 138 | 138 | |
| 139 | + | |
| 139 | 140 | |
| 140 | 141 | |
| 141 | 142 | |
| 4195 | 4196 | |
| 4196 | 4197 | |
| 4197 | 4198 | |
| 4198 | - | |
| 4199 | + | |
| 4200 | + | |
| 4201 | + | |
| 4202 | + | |
| 4199 | 4203 | |
| 4200 | 4204 | |
| 4201 | 4205 | |
| 121 | 121 | |
| 122 | 122 | |
| 123 | 123 | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 124 | 147 | |
| 125 | 148 | |
| 126 | 149 | |
| 130 | 153 | |
| 131 | 154 | |
| 132 | 155 | |
| 156 | + | |
| 133 | 157 | |
| 134 | 158 | |
| 135 | 159 | |
| 191 | 215 | |
| 192 | 216 | |
| 193 | 217 | |
| 194 | - | |
| 195 | - | |
| 196 | - | |
| 218 | + | |
| 219 | + | |
| 197 | 220 | |
| 198 | 221 | |
| 199 | 222 | |
| 262 | 285 | |
| 263 | 286 | |
| 264 | 287 | |
| 265 | - | |
| 288 | + | |
| 266 | 289 | |
| 267 | 290 | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 268 | 296 | |
| 269 | 297 | |
| 270 | - | |
| 271 | 298 | |
| 272 | 299 | |
| 273 | 300 | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 274 | 309 | |
| 275 | 310 | |
| 311 | + | |
| 276 | 312 | |
| 277 | 313 | |
| 278 | 314 | |
| 281 | 317 | |
| 282 | 318 | |
| 283 | 319 | |
| 320 | + | |
| 284 | 321 | |
| 285 | 322 | |
| 286 | 323 | |
| 287 | 324 | |
| 288 | - | |
| 325 | + | |
| 289 | 326 | |
| 290 | 327 | |
| 291 | 328 | |
| 298 | 335 | |
| 299 | 336 | |
| 300 | 337 | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 301 | 344 | |
| 302 | 345 | |
| 303 | 346 | |
| 146 | 146 | |
| 147 | 147 | |
| 148 | 148 | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 149 | 162 | |
| 150 | 163 | |
| 151 | 164 |
0 commit comments
Comments
No comments yet. Start the discussion.