From c54e3541b2fb6251bd7cd399e77037220b47de2e Mon Sep 17 00:00:00 2001 From: Mengdi Chen Date: Fri, 11 Nov 2022 15:18:06 -0500 Subject: [PATCH] [DevTools] bug fix for Hydrating fibers (#25663) ## Summary This PR is to fix a bug: an "element cannot be found" error when hydrating Server Components ### The problem image To reproduce: 1. setting up a vercel next.js 13 playground locally https://github.com/vercel/app-playground 2. visit http://localhost:3000/loading 3. click "electronics" button to navigate to http://localhost:3000/loading/electronics to trigger hydrating 4. inspect one of the skeleton card UI from React DevTools extension ### The root cause & fix This bug was introduced in #22527. When syncing reconciler changes, the value of `Hydrating` was copied from another variable `Visibility` (one more zero in the binary number). To avoid this kind of issue in the future, a new file `ReactFiberFlags` is created following the same format of the one in reconciler, so that it's easier to sync the number without making mistakes. The reconciler fiber flag file is also updated to reflect which of the flags are used in devtools ## How did you test this change? I build it locally and the bug no longer exist on http://localhost:3000/loading --- .../src/backend/ReactFiberFlags.js | 17 +++++++++ .../src/backend/renderer.js | 35 ++++--------------- .../react-reconciler/src/ReactFiberFlags.js | 8 ++--- 3 files changed, 28 insertions(+), 32 deletions(-) create mode 100644 packages/react-devtools-shared/src/backend/ReactFiberFlags.js diff --git a/packages/react-devtools-shared/src/backend/ReactFiberFlags.js b/packages/react-devtools-shared/src/backend/ReactFiberFlags.js new file mode 100644 index 0000000000000..aeece6acb9131 --- /dev/null +++ b/packages/react-devtools-shared/src/backend/ReactFiberFlags.js @@ -0,0 +1,17 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +// This list of flags must be synced with the following file: +// https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberFlags.js + +export const NoFlags = /* */ 0b00000000000000000000000000; +export const PerformedWork = /* */ 0b00000000000000000000000001; +export const Placement = /* */ 0b00000000000000000000000010; +export const DidCapture = /* */ 0b00000000000000000001000000; +export const Hydrating = /* */ 0b00000000000000100000000000; diff --git a/packages/react-devtools-shared/src/backend/renderer.js b/packages/react-devtools-shared/src/backend/renderer.js index cb3a8f2f407c7..68425faac8d7a 100644 --- a/packages/react-devtools-shared/src/backend/renderer.js +++ b/packages/react-devtools-shared/src/backend/renderer.js @@ -88,6 +88,13 @@ import { MEMO_SYMBOL_STRING, SERVER_CONTEXT_SYMBOL_STRING, } from './ReactSymbols'; +import { + DidCapture, + NoFlags, + PerformedWork, + Placement, + Hydrating, +} from './ReactFiberFlags'; import {format} from './utils'; import { enableProfilerChangedHookIndices, @@ -135,15 +142,6 @@ type ReactPriorityLevelsType = { NoPriority: number, }; -type ReactTypeOfSideEffectType = { - DidCapture: number, - NoFlags: number, - PerformedWork: number, - Placement: number, - Incomplete: number, - Hydrating: number, -}; - function getFiberFlags(fiber: Fiber): number { // The name of this field changed from "effectTag" to "flags" return fiber.flags !== undefined ? fiber.flags : (fiber: any).effectTag; @@ -162,19 +160,9 @@ export function getInternalReactConstants( getDisplayNameForFiber: getDisplayNameForFiberType, getTypeSymbol: getTypeSymbolType, ReactPriorityLevels: ReactPriorityLevelsType, - ReactTypeOfSideEffect: ReactTypeOfSideEffectType, ReactTypeOfWork: WorkTagMap, StrictModeBits: number, } { - const ReactTypeOfSideEffect: ReactTypeOfSideEffectType = { - DidCapture: 0b10000000, - NoFlags: 0b00, - PerformedWork: 0b01, - Placement: 0b10, - Incomplete: 0b10000000000000, - Hydrating: 0b1000000000000, - }; - // ********************************************************** // The section below is copied from files in React repo. // Keep it in sync, and add version guards if it changes. @@ -562,7 +550,6 @@ export function getInternalReactConstants( getTypeSymbol, ReactPriorityLevels, ReactTypeOfWork, - ReactTypeOfSideEffect, StrictModeBits, }; } @@ -595,16 +582,8 @@ export function attach( getTypeSymbol, ReactPriorityLevels, ReactTypeOfWork, - ReactTypeOfSideEffect, StrictModeBits, } = getInternalReactConstants(version); - const { - DidCapture, - Hydrating, - NoFlags, - PerformedWork, - Placement, - } = ReactTypeOfSideEffect; const { CacheComponent, ClassComponent, diff --git a/packages/react-reconciler/src/ReactFiberFlags.js b/packages/react-reconciler/src/ReactFiberFlags.js index d6eb8cd2529bc..cf0e40ff0a12c 100644 --- a/packages/react-reconciler/src/ReactFiberFlags.js +++ b/packages/react-reconciler/src/ReactFiberFlags.js @@ -11,22 +11,22 @@ import {enableCreateEventHandleAPI} from 'shared/ReactFeatureFlags'; export type Flags = number; -// Don't change these two values. They're used by React Dev Tools. +// Don't change these values. They're used by React Dev Tools. export const NoFlags = /* */ 0b00000000000000000000000000; export const PerformedWork = /* */ 0b00000000000000000000000001; +export const Placement = /* */ 0b00000000000000000000000010; +export const DidCapture = /* */ 0b00000000000000000001000000; +export const Hydrating = /* */ 0b00000000000000100000000000; // You can change the rest (and add more). -export const Placement = /* */ 0b00000000000000000000000010; export const Update = /* */ 0b00000000000000000000000100; export const ChildDeletion = /* */ 0b00000000000000000000001000; export const ContentReset = /* */ 0b00000000000000000000010000; export const Callback = /* */ 0b00000000000000000000100000; -export const DidCapture = /* */ 0b00000000000000000001000000; export const ForceClientRender = /* */ 0b00000000000000000010000000; export const Ref = /* */ 0b00000000000000000100000000; export const Snapshot = /* */ 0b00000000000000001000000000; export const Passive = /* */ 0b00000000000000010000000000; -export const Hydrating = /* */ 0b00000000000000100000000000; export const Visibility = /* */ 0b00000000000001000000000000; export const StoreConsistency = /* */ 0b00000000000010000000000000;