Shared Runtime Utilities
The packages/shared helpers provide common runtime behavior for identifying element types, deriving component names, and comparing values shallowly. They are used where renderer-independent decisions must stay consistent across React’s packages.
Keeping these operations shared avoids each consumer inventing a slightly different naming or equality rule. The shown call sites include JSX task naming, reconciler warnings, memo bailouts, and pure class updates, so consistency affects both diagnostics and rendering work.
Sources: packages/shared/getComponentNameFromType.js:57-134, packages/shared/shallowEqual.js:18-52, packages/react-reconciler/src/ReactFiber.js:691-704, packages/react-reconciler/src/ReactFiberBeginWork.js:529-536, packages/react-reconciler/src/ReactFiberClassComponent.js:287-293
Core concepts
Component name resolution
A component name is a human-readable label derived from a type so warnings and developer-facing output can identify what React is processing. getComponentNameFromType returns names for functions, host strings, built-in symbols, and several wrapped object types.
Sources: packages/shared/getComponentNameFromType.js:57-134
Shallow equality
Shallow equality means two values match by identity, or two non-null objects have the same own keys whose values match by identity. shallowEqual implements that comparison.
Sources: packages/shared/shallowEqual.js:18-52
Array detection
Array detection is a small wrapper around the platform array predicate. isArray delegates to isArrayImpl, which is assigned from Array.isArray.
Sources: packages/shared/isArray.js:15, packages/shared/isArray.js:17-19
Why these helpers are shared
The shared package is useful because the same low-level decisions occur at different boundaries. JSX uses getComponentNameFromType to build a task label, while the reconciler uses it when describing an invalid element type in a warning.
The equality helper also serves more than one reconciler path: memoized components use it as their default prop comparator, and pure class components use it for both props and state.
This arrangement makes the shared implementation the common policy rather than duplicating equivalent logic in each consumer. The evidence also shows a renderer package importing the shared naming helper directly, demonstrating that the helper crosses package boundaries.
Sources: packages/react-reconciler/src/ReactFiber.js:691-704, packages/react-reconciler/src/ReactFiberBeginWork.js:529-534, packages/react-reconciler/src/ReactFiberClassComponent.js:287-293, packages/react-native-renderer/src/ReactNativePublicCompat.js:26-35
How a type becomes a warning name
getComponentNameFromType first handles nullish values, functions, and strings. Nullish values produce no name, functions prefer displayName and then name, and strings are returned directly.
It then recognizes built-in React type symbols and returns stable labels such as Fragment, Profiler, StrictMode, Suspense, SuspenseList, and Activity. Feature-gated view-transition and tracing-marker types only receive their labels when the corresponding flag is enabled.
For object types, the helper dispatches on type.$$typeof. Portals receive Portal; contexts use getContextName; consumers append .Consumer; forward refs use getWrappedName; memo types prefer their outer displayName and otherwise recurse into the wrapped type; lazy types initialize their payload and recurse, returning null if initialization throws.
The naming call order below shows the helper calls that are visible in the supplied implementation; the lazy path is deliberately represented as a call to init, not as an assumption about what initialization does.
Evidence
getWrappedName preserves an outer displayName; otherwise it formats the inner function name as wrapperName(functionName), or returns only the wrapper name when the inner type has no name.
getContextName uses a context’s displayName, falling back to Context. The client-reference marker is REACT_CLIENT_REFERENCE; functions carrying it return no name because the implementation does not establish a naming convention for those references.
Sources: packages/shared/getComponentNameFromType.js:57-70, packages/shared/getComponentNameFromType.js:72-94, packages/shared/getComponentNameFromType.js:95-133, packages/shared/getComponentNameFromType.js:57-134, packages/shared/getComponentNameFromType.js:36-47, packages/shared/getComponentNameFromType.js:50-52, packages/shared/getComponentNameFromType.js:54, packages/shared/getComponentNameFromType.js:62-67
How shallow equality controls work
shallowEqual first checks whether the two inputs are identical under is. If not, it rejects primitives and null values, compares the number of own keys, and then verifies that every key exists on the second object with an identical value.
In the reconciler’s memo path, Component.compare is used when supplied; otherwise the comparison defaults to shallowEqual. If props compare equal and the ref is unchanged, React bails out of already-finished work.
For pure class components, shallowEqual is applied independently to old versus new props and old versus new state. The component is considered needing an update when either comparison differs.
The supplied material does not show a public API call site for shallowEqual; it establishes its reconciler uses, not a separate public export or public-API contract.
Sources: packages/react-reconciler/src/ReactFiberBeginWork.js:529-536, packages/react-reconciler/src/ReactFiberClassComponent.js:287-293, packages/shared/shallowEqual.js:18-52
How array detection stays minimal
isArrayImpl stores the platform’s Array.isArray, and isArray forwards its argument to that implementation. This gives shared callers a named helper without adding another classification rule.
The reconciler uses isArray while classifying an invalid component type for a warning, mapping an array type to the label array.
Sources: packages/shared/isArray.js:15, packages/shared/isArray.js:17-19, packages/react-reconciler/src/ReactFiber.js:686-700
How it connects
The shared naming helper feeds JSX task labels, where a resolved name becomes <Name> and an unavailable name becomes <...>. This connects to Public API Reference and Element Types & Components.
The reconciler uses the same naming and equality utilities during warning construction, memo bailout checks, and class update checks. This connects to Fiber Architecture, Reconciliation Algorithm, and Render Phase.
A renderer package can import the shared name resolver directly, while build configuration also treats shared internals as package-boundary-sensitive modules. This connects to Repository Map and Rollup Bundles & Module Forks.
Sources: packages/react/src/jsx/ReactJSXElement.js:29-47, packages/react-reconciler/src/ReactFiber.js:691-704, packages/react-reconciler/src/ReactFiberBeginWork.js:529-536, packages/react-reconciler/src/ReactFiberClassComponent.js:287-293, packages/react-native-renderer/src/ReactNativePublicCompat.js:26-35
Key takeaways
getComponentNameFromTypeconverts functions, strings, built-ins, contexts, wrappers, memo types, and lazy types into diagnostic names when possible.getWrappedNameandgetContextNamecentralize naming conventions for wrapped components and contexts.shallowEqualis the default memo comparison and supports pure-class props/state checks.isArrayis a thin shared wrapper around Array.isArray.
Sources: packages/shared/getComponentNameFromType.js:57-134, packages/shared/getComponentNameFromType.js:36-47, packages/shared/getComponentNameFromType.js:50-52, packages/react-reconciler/src/ReactFiberBeginWork.js:529-534, packages/react-reconciler/src/ReactFiberClassComponent.js:287-293, packages/shared/isArray.js:15, packages/shared/isArray.js:17-19