Repository: facebook/react
Pull request: Dedupe legacy context warnings


Similar to other warnings about legacy APIs, only raise a warning once per component.

.
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/30299).
* #30297
* __->__ #30299

Changed files:
filename: packages/react-dom/src/__tests__/ReactDOMServerIntegrationLegacyContextDisabled-test.internal.js
patch: @@ -34,8 +34,7 @@ function initModules() {
   };
 }
 
-const {resetModules, itRenders, clientRenderOnBadMarkup} =
-  ReactDOMServerIntegrationUtils(initModules);
+const {resetModules, itRenders} = ReactDOMServerIntegrationUtils(initModules);
 
 function formatValue(val) {
   if (val === null) {
@@ -105,7 +104,7 @@ describe('ReactDOMServerIntegrationLegacyContextDisabled', () => {
           <RegularFn />
         </span>
       </LegacyProvider>,
-      render === clientRenderOnBadMarkup ? 4 : 3,
+      3,
     );
     expect(e.textContent).toBe('{}undefinedundefined');
     expect(lifecycleContextLog).toEqual([]);

filename: packages/react-reconciler/src/ReactFiberClassComponent.js
patch: @@ -82,6 +82,8 @@ let didWarnAboutLegacyLifecyclesAndDerivedState;
 let didWarnAboutUndefinedDerivedState;
 let didWarnAboutDirectlyAssigningPropsToState;
 let didWarnAboutContextTypeAndContextTypes;
+let didWarnAboutContextTypes;
+let didWarnAboutChildContextTypes;
 let didWarnAboutInvalidateContextType;
 let didWarnOnInvalidCallback;
 
@@ -93,6 +95,8 @@ if (__DEV__) {
   didWarnAboutDirectlyAssigningPropsToState = new Set<string>();
   didWarnAboutUndefinedDerivedState = new Set<string>();
   didWarnAboutContextTypeAndContextTypes = new Set<string>();
+  didWarnAboutContextTypes = new Set<mixed>();
+  didWarnAboutChildContextTypes = new Set<mixed>();
   didWarnAboutInvalidateContextType = new Set<string>();
   didWarnOnInvalidCallback = new Set<string>();
 
@@ -385,14 +389,16 @@ function checkClassInstance(workInProgress: Fiber, ctor: any, newProps: any) {
     }
 
     if (disableLegacyContext) {
-      if (ctor.childContextTypes) {
+      if (ctor.childContextTypes && !didWarnAboutChildContextTypes.has(ctor)) {
+        didWarnAboutChildContextTypes.add(ctor);
         console.error(
           '%s uses the legacy childContextTypes API which was removed in React 19. ' +
             'Use React.createContext() instead.',
           name,
         );
       }
-      if (ctor.contextTypes) {
+      if (ctor.contextTypes && !didWarnAboutContextTypes.has(ctor)) {
+        didWarnAboutContextTypes.add(ctor);
         console.error(
           '%s uses the legacy contextTypes API which was removed in React 19. ' +
             'Use React.createContext() with static contextType instead.',

filename: packages/react-server/src/ReactFizzClassComponent.js
patch: @@ -26,6 +26,8 @@ let didWarnAboutLegacyLifecyclesAndDerivedState;
 let didWarnAboutUndefinedDerivedState;
 let didWarnAboutDirectlyAssigningPropsToState;
 let didWarnAboutContextTypeAndContextTypes;
+let didWarnAboutContextTypes;
+let didWarnAboutChildContextTypes;
 let didWarnAboutInvalidateContextType;
 let didWarnOnInvalidCallback;
 
@@ -36,6 +38,8 @@ if (__DEV__) {
   didWarnAboutDirectlyAssigningPropsToState = new Set<string>();
   didWarnAboutUndefinedDerivedState = new Set<string>();
   didWarnAboutContextTypeAndContextTypes = new Set<mixed>();
+  didWarnAboutContextTypes = new Set<mixed>();
+  didWarnAboutChildContextTypes = new Set<mixed>();
   didWarnAboutInvalidateContextType = new Set<mixed>();
   didWarnOnInvalidCallback = new Set<string>();
 }
@@ -362,14 +366,16 @@ function checkClassInstance(instance: any, ctor: any, newProps: any) {
     }
 
     if (disableLegacyContext) {
-      if (ctor.childContextTypes) {
+      if (ctor.childContextTypes && !didWarnAboutChildContextTypes.has(ctor)) {
+        didWarnAboutChildContextTypes.add(ctor);
         console.error(
           '%s uses the legacy childContextTypes API which was removed in React 19. ' +
             'Use React.createContext() instead.',
           name,
         );
       }
-      if (ctor.contextTypes) {
+      if (ctor.contextTypes && !didWarnAboutContextTypes.has(ctor)) {
+        didWarnAboutContextTypes.add(ctor);
         console.error(
           '%s uses the legacy contextTypes API which was removed in React 19. ' +
             'Use React.createContext() with static contextType instead.',