From c902bb50cf0a3a1ca8049b2e4ccbe5f4dd1b096e Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Thu, 11 Oct 2018 15:45:48 +0100 Subject: [PATCH 01/14] Deprecate context object as a cosumer and add a warning message --- .../src/ReactFiberBeginWork.js | 22 +++++++++- .../ReactNewContext-test.internal.js | 31 +++++++++++++- packages/react/src/ReactContext.js | 41 ++++++++++++++++++- 3 files changed, 90 insertions(+), 4 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index d5b3545622862..d605cde441697 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -8,6 +8,7 @@ */ import type {ReactProviderType, ReactContext} from 'shared/ReactTypes'; +import lowPriorityWarning from 'shared/lowPriorityWarning'; import type {Fiber} from 'react-reconciler/src/ReactFiber'; import type {FiberRoot} from './ReactFiberRoot'; import type {ExpirationTime} from './ReactFiberExpirationTime'; @@ -1096,12 +1097,31 @@ function updateContextProvider( return workInProgress.child; } +let hasWarnedAboutUsingContextAsConsumer = false; + function updateContextConsumer( current: Fiber | null, workInProgress: Fiber, renderExpirationTime: ExpirationTime, ) { - const context: ReactContext = workInProgress.type; + let context: ReactContext = workInProgress.type; + if (__DEV__) { + if (workInProgress.type._context === undefined) { + if (!hasWarnedAboutUsingContextAsConsumer) { + hasWarnedAboutUsingContextAsConsumer = true; + lowPriorityWarning( + false, + 'You are using the Context from React.createContext() as a consumer.' + + 'The correct way is to use Context.Consumer as the consumer instead. ' + + 'This usage is deprecated and will be removed in the next major version.', + ); + } + } else { + // Context.Consumer is a separate object in DEV, where + // _context points back to the original context + context = workInProgress.type._context; + } + } const newProps = workInProgress.pendingProps; const render = newProps.children; diff --git a/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js b/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js index 9570a25e45bee..bbb2cc271fb9d 100644 --- a/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js @@ -1190,12 +1190,12 @@ describe('ReactNewContext', () => { function FooAndBar() { return ( - + {foo => { const bar = BarContext.unstable_read(); return ; }} - + ); } @@ -1558,4 +1558,31 @@ Context fuzz tester error! Copy and paste the following line into the test suite } }); }); + + it('should warn with an error message when using context as a consumer in DEV', () => { + const BarContext = React.createContext({value: 'bar-initial'}); + const BarConsumer = BarContext; + + function Component() { + return ( + + + + {({value}) =>
} + + + + ); + } + + expect(() => { + ReactNoop.render(); + ReactNoop.flush(); + }).toLowPriorityWarnDev( + 'You are using the Context from React.createContext() as a consumer.' + + 'The correct way is to use Context.Consumer as the consumer instead. ' + + 'This usage is deprecated and will be removed in the next major version.', + {withoutStack: true}, + ); + }); }); diff --git a/packages/react/src/ReactContext.js b/packages/react/src/ReactContext.js index bf63f8dfa7d1a..21a4961c377b9 100644 --- a/packages/react/src/ReactContext.js +++ b/packages/react/src/ReactContext.js @@ -67,7 +67,46 @@ export function createContext( $$typeof: REACT_PROVIDER_TYPE, _context: context, }; - context.Consumer = context; + + if (__DEV__) { + // A separate object, but proxies back to the original context object for + // backwards compatibility. It has a different $$typeof, so we can properly + // warn for the incorrect usage of Context as a Consumer. + context.Consumer = { + $$typeof: REACT_CONTEXT_TYPE, + _context: context, + get _calculateChangedBits() { + return context._calculateChangedBits; + }, + set _calculateChangedBits(_calculateChangedBits) { + context._calculateChangedBits = _calculateChangedBits; + }, + get _currentValue() { + return context._currentValue; + }, + set _currentValue(_currentValue) { + context._currentValue = _currentValue; + }, + get _currentValue2() { + return context._currentValue2; + }, + set _currentValue2(_currentValue2) { + context._currentValue2 = _currentValue2; + }, + Provider: context.Provider, + get Consumer() { + return context.Consumer; + }, + get unstable_read() { + return context.unstable_read; + }, + set unstable_read(unstable_read) { + context.unstable_read = unstable_read; + }, + }; + } else { + context.Consumer = context; + } context.unstable_read = readContext.bind(null, context); if (__DEV__) { From bd3495c0a7bd3d3941322df22ec8dd76d888e265 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Thu, 11 Oct 2018 16:54:12 +0100 Subject: [PATCH 02/14] change to Object.defineProperties --- packages/react/src/ReactContext.js | 65 ++++++++++++++++++------------ 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/packages/react/src/ReactContext.js b/packages/react/src/ReactContext.js index 21a4961c377b9..0c380614528b9 100644 --- a/packages/react/src/ReactContext.js +++ b/packages/react/src/ReactContext.js @@ -72,38 +72,53 @@ export function createContext( // A separate object, but proxies back to the original context object for // backwards compatibility. It has a different $$typeof, so we can properly // warn for the incorrect usage of Context as a Consumer. - context.Consumer = { + const consumer = { $$typeof: REACT_CONTEXT_TYPE, _context: context, - get _calculateChangedBits() { - return context._calculateChangedBits; - }, - set _calculateChangedBits(_calculateChangedBits) { - context._calculateChangedBits = _calculateChangedBits; - }, - get _currentValue() { - return context._currentValue; - }, - set _currentValue(_currentValue) { - context._currentValue = _currentValue; - }, - get _currentValue2() { - return context._currentValue2; + Provider: context.Provider, + }; + // $FlowFixMe: Flow complains about not setting a value, which is intentional here + Object.defineProperties(consumer, { + _calculateChangedBits: { + get() { + return context._calculateChangedBits; + }, + set(_calculateChangedBits) { + context._calculateChangedBits = _calculateChangedBits; + }, }, - set _currentValue2(_currentValue2) { - context._currentValue2 = _currentValue2; + _currentValue: { + get() { + return context._currentValue; + }, + set(_currentValue) { + context._currentValue = _currentValue; + }, }, - Provider: context.Provider, - get Consumer() { - return context.Consumer; + _currentValue2: { + get() { + return context._currentValue2; + }, + set(_currentValue2) { + context._currentValue2 = _currentValue2; + }, }, - get unstable_read() { - return context.unstable_read; + Consumer: { + get() { + return context.Consumer; + }, }, - set unstable_read(unstable_read) { - context.unstable_read = unstable_read; + unstable_read: { + get() { + return context.unstable_read; + }, + set(unstable_read) { + context.unstable_read = unstable_read; + }, }, - }; + }); + // $FlowFixMe: Flow complains about missing properties because it doesn't understand defineProperty + context.Consumer = consumer; } else { context.Consumer = context; } From 6d7d7c04554fbbc057c3cfdd65e28bf6b8965710 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 12 Oct 2018 10:41:37 +0100 Subject: [PATCH 03/14] updated comments --- packages/react-reconciler/src/ReactFiberBeginWork.js | 11 ++++++++--- .../src/__tests__/ReactNewContext-test.internal.js | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index d605cde441697..f934faa882d46 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -1105,6 +1105,13 @@ function updateContextConsumer( renderExpirationTime: ExpirationTime, ) { let context: ReactContext = workInProgress.type; + // The logic below for Context differs depending on PROD or DEV mode. In + // DEV mode, we create a separate object for Context.Consumer that acts + // like a proxy to Context. This proxy object adds unecessary code in PROD + // so we use the old behaviour (Context.Consumer references Context) to + // reduce size and overhead. The separate object references context via + // a property called "_context", which also gives us the ability to check + // in DEV mode if this property exists or not and warn if it does not. if (__DEV__) { if (workInProgress.type._context === undefined) { if (!hasWarnedAboutUsingContextAsConsumer) { @@ -1113,12 +1120,10 @@ function updateContextConsumer( false, 'You are using the Context from React.createContext() as a consumer.' + 'The correct way is to use Context.Consumer as the consumer instead. ' + - 'This usage is deprecated and will be removed in the next major version.', + 'This usage is deprecated and will be removed in a future major release.', ); } } else { - // Context.Consumer is a separate object in DEV, where - // _context points back to the original context context = workInProgress.type._context; } } diff --git a/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js b/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js index bbb2cc271fb9d..ba34d21e39458 100644 --- a/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js @@ -1581,7 +1581,7 @@ Context fuzz tester error! Copy and paste the following line into the test suite }).toLowPriorityWarnDev( 'You are using the Context from React.createContext() as a consumer.' + 'The correct way is to use Context.Consumer as the consumer instead. ' + - 'This usage is deprecated and will be removed in the next major version.', + 'This usage is deprecated and will be removed in a future major release.', {withoutStack: true}, ); }); From 773d69d98b6242b645a5c19a8b69e591ce9fa512 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 12 Oct 2018 10:52:23 +0100 Subject: [PATCH 04/14] fix typo --- packages/react-reconciler/src/ReactFiberBeginWork.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index f934faa882d46..8171f37330ce2 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -1107,7 +1107,7 @@ function updateContextConsumer( let context: ReactContext = workInProgress.type; // The logic below for Context differs depending on PROD or DEV mode. In // DEV mode, we create a separate object for Context.Consumer that acts - // like a proxy to Context. This proxy object adds unecessary code in PROD + // like a proxy to Context. This proxy object adds unnecessary code in PROD // so we use the old behaviour (Context.Consumer references Context) to // reduce size and overhead. The separate object references context via // a property called "_context", which also gives us the ability to check From 22f4359b70bdaafc8d963f36275473fb24e938f0 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 12 Oct 2018 11:26:58 +0100 Subject: [PATCH 05/14] address feedback --- packages/react-reconciler/src/ReactFiberBeginWork.js | 12 +++++------- .../src/__tests__/ReactNewContext-test.internal.js | 8 +++----- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index 8171f37330ce2..fd303aeadc332 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -8,7 +8,6 @@ */ import type {ReactProviderType, ReactContext} from 'shared/ReactTypes'; -import lowPriorityWarning from 'shared/lowPriorityWarning'; import type {Fiber} from 'react-reconciler/src/ReactFiber'; import type {FiberRoot} from './ReactFiberRoot'; import type {ExpirationTime} from './ReactFiberExpirationTime'; @@ -1113,18 +1112,17 @@ function updateContextConsumer( // a property called "_context", which also gives us the ability to check // in DEV mode if this property exists or not and warn if it does not. if (__DEV__) { - if (workInProgress.type._context === undefined) { + if (context._context === undefined) { if (!hasWarnedAboutUsingContextAsConsumer) { hasWarnedAboutUsingContextAsConsumer = true; - lowPriorityWarning( + warning( false, - 'You are using the Context from React.createContext() as a consumer.' + - 'The correct way is to use Context.Consumer as the consumer instead. ' + - 'This usage is deprecated and will be removed in a future major release.', + 'Rendering directly is not supported and will be removed in ' + + 'a future major release. Did you mean to render instead?', ); } } else { - context = workInProgress.type._context; + context = context._context; } } const newProps = workInProgress.pendingProps; diff --git a/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js b/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js index ba34d21e39458..d996c494ecdcd 100644 --- a/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js @@ -1578,11 +1578,9 @@ Context fuzz tester error! Copy and paste the following line into the test suite expect(() => { ReactNoop.render(); ReactNoop.flush(); - }).toLowPriorityWarnDev( - 'You are using the Context from React.createContext() as a consumer.' + - 'The correct way is to use Context.Consumer as the consumer instead. ' + - 'This usage is deprecated and will be removed in a future major release.', - {withoutStack: true}, + }).toWarnDev( + 'Rendering directly is not supported and will be removed in ' + + 'a future major release. Did you mean to render instead?', ); }); }); From e39a444a3c509f06aa718c520cd68f16a05cbda1 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 12 Oct 2018 11:35:12 +0100 Subject: [PATCH 06/14] fix flow --- packages/react-reconciler/src/ReactFiberBeginWork.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index fd303aeadc332..54c5b457368ec 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -1112,7 +1112,7 @@ function updateContextConsumer( // a property called "_context", which also gives us the ability to check // in DEV mode if this property exists or not and warn if it does not. if (__DEV__) { - if (context._context === undefined) { + if ((context: any)._context === undefined) { if (!hasWarnedAboutUsingContextAsConsumer) { hasWarnedAboutUsingContextAsConsumer = true; warning( @@ -1122,7 +1122,7 @@ function updateContextConsumer( ); } } else { - context = context._context; + context = (context: any)._context; } } const newProps = workInProgress.pendingProps; From 40fcddb6cb9b63ca9e5cd4839c269849d11bd83b Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 12 Oct 2018 11:52:03 +0100 Subject: [PATCH 07/14] prettier --- packages/react-reconciler/src/ReactFiberBeginWork.js | 2 +- .../src/__tests__/ReactNewContext-test.internal.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index 54c5b457368ec..9d17783d721b6 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -1118,7 +1118,7 @@ function updateContextConsumer( warning( false, 'Rendering directly is not supported and will be removed in ' + - 'a future major release. Did you mean to render instead?', + 'a future major release. Did you mean to render instead?', ); } } else { diff --git a/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js b/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js index d996c494ecdcd..0629f0947343f 100644 --- a/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js @@ -1580,7 +1580,7 @@ Context fuzz tester error! Copy and paste the following line into the test suite ReactNoop.flush(); }).toWarnDev( 'Rendering directly is not supported and will be removed in ' + - 'a future major release. Did you mean to render instead?', + 'a future major release. Did you mean to render instead?', ); }); }); From 4b0c8a76c6bb163b89c58880e3f7e0cd72dfae0f Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 12 Oct 2018 14:04:34 +0100 Subject: [PATCH 08/14] Warn against Context.Consumer.Consumer --- .../ReactNewContext-test.internal.js | 25 +++++++++++++++++++ packages/react/src/ReactContext.js | 11 ++++++++ 2 files changed, 36 insertions(+) diff --git a/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js b/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js index 0629f0947343f..7869a150739fa 100644 --- a/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js @@ -1583,4 +1583,29 @@ Context fuzz tester error! Copy and paste the following line into the test suite 'a future major release. Did you mean to render instead?', ); }); + + it('should warn with an error message when using nested context consumers in DEV', () => { + const BarContext = React.createContext({value: 'bar-initial'}); + const BarConsumer = BarContext; + + function Component() { + return ( + + + + {({value}) =>
} + + + + ); + } + + expect(() => { + ReactNoop.render(); + ReactNoop.flush(); + }).toWarnDev( + 'Rendering is not supported and will be removed in ' + + 'a future major release. Did you mean to render instead?', + ); + }); }); diff --git a/packages/react/src/ReactContext.js b/packages/react/src/ReactContext.js index 0c380614528b9..a1410b419eb57 100644 --- a/packages/react/src/ReactContext.js +++ b/packages/react/src/ReactContext.js @@ -13,6 +13,7 @@ import type {ReactContext} from 'shared/ReactTypes'; import invariant from 'shared/invariant'; import warningWithoutStack from 'shared/warningWithoutStack'; +import warning from 'shared/warning'; import ReactCurrentOwner from './ReactCurrentOwner'; @@ -68,6 +69,8 @@ export function createContext( _context: context, }; + let hasWarnedAboutUsingNestedContextConsumers = false; + if (__DEV__) { // A separate object, but proxies back to the original context object for // backwards compatibility. It has a different $$typeof, so we can properly @@ -105,6 +108,14 @@ export function createContext( }, Consumer: { get() { + if (!hasWarnedAboutUsingNestedContextConsumers) { + hasWarnedAboutUsingNestedContextConsumers = true; + warning( + false, + 'Rendering is not supported and will be removed in ' + + 'a future major release. Did you mean to render instead?', + ); + } return context.Consumer; }, }, From f174b6e0d63e6cf550b6a1810a280bca6f7ed338 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 12 Oct 2018 14:41:45 +0100 Subject: [PATCH 09/14] more changes based on feedback --- packages/react/src/ReactContext.js | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/packages/react/src/ReactContext.js b/packages/react/src/ReactContext.js index a1410b419eb57..82da325fb3330 100644 --- a/packages/react/src/ReactContext.js +++ b/packages/react/src/ReactContext.js @@ -78,18 +78,12 @@ export function createContext( const consumer = { $$typeof: REACT_CONTEXT_TYPE, _context: context, + _calculateChangedBits: context._calculateChangedBits, Provider: context.Provider, + unstable_read: context.unstable_read, }; // $FlowFixMe: Flow complains about not setting a value, which is intentional here Object.defineProperties(consumer, { - _calculateChangedBits: { - get() { - return context._calculateChangedBits; - }, - set(_calculateChangedBits) { - context._calculateChangedBits = _calculateChangedBits; - }, - }, _currentValue: { get() { return context._currentValue; @@ -119,14 +113,6 @@ export function createContext( return context.Consumer; }, }, - unstable_read: { - get() { - return context.unstable_read; - }, - set(unstable_read) { - context.unstable_read = unstable_read; - }, - }, }); // $FlowFixMe: Flow complains about missing properties because it doesn't understand defineProperty context.Consumer = consumer; From 59917cdb91ce73f42cc8eae6ed5dab0602776861 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 12 Oct 2018 14:44:44 +0100 Subject: [PATCH 10/14] move line --- packages/react/src/ReactContext.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/react/src/ReactContext.js b/packages/react/src/ReactContext.js index 82da325fb3330..6fdc7b86c4499 100644 --- a/packages/react/src/ReactContext.js +++ b/packages/react/src/ReactContext.js @@ -69,6 +69,8 @@ export function createContext( _context: context, }; + context.unstable_read = readContext.bind(null, context); + let hasWarnedAboutUsingNestedContextConsumers = false; if (__DEV__) { @@ -119,7 +121,6 @@ export function createContext( } else { context.Consumer = context; } - context.unstable_read = readContext.bind(null, context); if (__DEV__) { context._currentRenderer = null; From 072b0d4346f7fc145dee7f651a50626ee0d729cb Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 12 Oct 2018 16:01:29 +0100 Subject: [PATCH 11/14] Add another warning --- .../ReactNewContext-test.internal.js | 27 +++++++++++++++++++ packages/react/src/ReactContext.js | 13 ++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js b/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js index 7869a150739fa..9db612ca0400a 100644 --- a/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js @@ -1608,4 +1608,31 @@ Context fuzz tester error! Copy and paste the following line into the test suite 'a future major release. Did you mean to render instead?', ); }); + + it('should warn with an error message when using Context.Consumer.unstable_read() DEV', () => { + const BarContext = React.createContext({value: 'bar-initial'}); + + function Child() { + let value = BarContext.Consumer.unstable_read(); + return
; + } + + function Component() { + return ( + + + + + + ); + } + + expect(() => { + ReactNoop.render(); + ReactNoop.flush(); + }).toWarnDev( + 'Calling Context.Consumer.unstable_read() is not supported and will be removed in ' + + 'a future major release. Did you mean to render Context.unstable_read() instead?', + ); + }); }); diff --git a/packages/react/src/ReactContext.js b/packages/react/src/ReactContext.js index 6fdc7b86c4499..2906fedceefe0 100644 --- a/packages/react/src/ReactContext.js +++ b/packages/react/src/ReactContext.js @@ -72,6 +72,7 @@ export function createContext( context.unstable_read = readContext.bind(null, context); let hasWarnedAboutUsingNestedContextConsumers = false; + let hasWarnedAboutUsingConsumerUnstableRead = false; if (__DEV__) { // A separate object, but proxies back to the original context object for @@ -82,7 +83,17 @@ export function createContext( _context: context, _calculateChangedBits: context._calculateChangedBits, Provider: context.Provider, - unstable_read: context.unstable_read, + unstable_read() { + if (!hasWarnedAboutUsingConsumerUnstableRead) { + hasWarnedAboutUsingConsumerUnstableRead = true; + warning( + false, + 'Calling Context.Consumer.unstable_read() is not supported and will be removed in ' + + 'a future major release. Did you mean to render Context.unstable_read() instead?', + ); + } + return context.unstable_read(); + }, }; // $FlowFixMe: Flow complains about not setting a value, which is intentional here Object.defineProperties(consumer, { From 26d6d2c203dece291f8a776c8bf799d89a1e5e5a Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 12 Oct 2018 17:34:05 +0100 Subject: [PATCH 12/14] address more feedback --- .../ReactNewContext-test.internal.js | 24 +++++++++++++++++++ packages/react/src/ReactContext.js | 18 +++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js b/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js index 9db612ca0400a..8ca7ab632d6de 100644 --- a/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js @@ -1635,4 +1635,28 @@ Context fuzz tester error! Copy and paste the following line into the test suite 'a future major release. Did you mean to render Context.unstable_read() instead?', ); }); + + it('should warn with an error message when using Context.Consumer.Provider DEV', () => { + const BarContext = React.createContext({value: 'bar-initial'}); + + function Component() { + return ( + + + + {({value}) =>
} + + + + ); + } + + expect(() => { + ReactNoop.render(); + ReactNoop.flush(); + }).toWarnDev( + 'Rendering is not supported and will be removed in ' + + 'a future major release. Did you mean to render instead?', + ); + }); }); diff --git a/packages/react/src/ReactContext.js b/packages/react/src/ReactContext.js index 2906fedceefe0..e6434f53d5ced 100644 --- a/packages/react/src/ReactContext.js +++ b/packages/react/src/ReactContext.js @@ -73,6 +73,7 @@ export function createContext( let hasWarnedAboutUsingNestedContextConsumers = false; let hasWarnedAboutUsingConsumerUnstableRead = false; + let hasWarnedAboutUsingConsumerProvider = false; if (__DEV__) { // A separate object, but proxies back to the original context object for @@ -82,7 +83,6 @@ export function createContext( $$typeof: REACT_CONTEXT_TYPE, _context: context, _calculateChangedBits: context._calculateChangedBits, - Provider: context.Provider, unstable_read() { if (!hasWarnedAboutUsingConsumerUnstableRead) { hasWarnedAboutUsingConsumerUnstableRead = true; @@ -97,6 +97,22 @@ export function createContext( }; // $FlowFixMe: Flow complains about not setting a value, which is intentional here Object.defineProperties(consumer, { + Provider: { + get() { + if (!hasWarnedAboutUsingConsumerProvider) { + hasWarnedAboutUsingConsumerProvider = true; + warning( + false, + 'Rendering is not supported and will be removed in ' + + 'a future major release. Did you mean to render instead?', + ); + } + return context.Provider; + }, + set(_Provider) { + context.Provider = _Provider; + }, + }, _currentValue: { get() { return context._currentValue; From d058f6eaae023051f5788d1ca4917442b282c689 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 12 Oct 2018 17:35:51 +0100 Subject: [PATCH 13/14] prettier --- .../src/__tests__/ReactNewContext-test.internal.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js b/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js index 8ca7ab632d6de..03b52dccdc863 100644 --- a/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactNewContext-test.internal.js @@ -1656,7 +1656,7 @@ Context fuzz tester error! Copy and paste the following line into the test suite ReactNoop.flush(); }).toWarnDev( 'Rendering is not supported and will be removed in ' + - 'a future major release. Did you mean to render instead?', + 'a future major release. Did you mean to render instead?', ); - }); + }); }); From 9149b17b4d8bba74050a8d49bc522cb5ca309456 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 12 Oct 2018 17:41:41 +0100 Subject: [PATCH 14/14] address nit --- packages/react/src/ReactContext.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react/src/ReactContext.js b/packages/react/src/ReactContext.js index e6434f53d5ced..fa9ff223f83cb 100644 --- a/packages/react/src/ReactContext.js +++ b/packages/react/src/ReactContext.js @@ -79,7 +79,7 @@ export function createContext( // A separate object, but proxies back to the original context object for // backwards compatibility. It has a different $$typeof, so we can properly // warn for the incorrect usage of Context as a Consumer. - const consumer = { + const Consumer = { $$typeof: REACT_CONTEXT_TYPE, _context: context, _calculateChangedBits: context._calculateChangedBits, @@ -96,7 +96,7 @@ export function createContext( }, }; // $FlowFixMe: Flow complains about not setting a value, which is intentional here - Object.defineProperties(consumer, { + Object.defineProperties(Consumer, { Provider: { get() { if (!hasWarnedAboutUsingConsumerProvider) { @@ -144,7 +144,7 @@ export function createContext( }, }); // $FlowFixMe: Flow complains about missing properties because it doesn't understand defineProperty - context.Consumer = consumer; + context.Consumer = Consumer; } else { context.Consumer = context; }