From 6d3ecb70dceb225af0cd990b46d6c44b852c1d82 Mon Sep 17 00:00:00 2001 From: Andrew Clark Date: Fri, 19 Mar 2021 17:36:51 -0500 Subject: [PATCH] Remove unstable_changedBits (#20953) We added this unstable feature a few years ago, as a way to opt out of context updates, but it didn't prove useful in practice. We have other proposals for how to address the same problem, like context selectors. Since it was prefixed with `unstable_`, we should be able to remove it without consequence. The hook API already warned if you used it. Even if someone is using it somewhere, it's meant to be an optimization only, so if they are using the API properly, it should not have any semantic impact. --- packages/react-cache/src/ReactCacheOld.js | 4 +- .../react-debug-tools/src/ReactDebugHooks.js | 10 +- .../src/devtools/cache.js | 4 +- .../ReactDOMServerIntegrationHooks-test.js | 15 +- ...eactDOMServerIntegrationNewContext-test.js | 4 +- .../src/server/ReactPartialRendererHooks.js | 10 +- .../src/ReactFiberBeginWork.new.js | 29 +- .../src/ReactFiberBeginWork.old.js | 29 +- .../src/ReactFiberCacheComponent.new.js | 1 - .../src/ReactFiberCacheComponent.old.js | 1 - .../src/ReactFiberHooks.new.js | 98 ++---- .../src/ReactFiberHooks.old.js | 98 ++---- .../src/ReactFiberNewContext.new.js | 87 +---- .../src/ReactFiberNewContext.old.js | 87 +---- .../src/ReactInternalTypes.js | 11 +- .../src/__tests__/ReactNewContext-test.js | 307 +----------------- packages/react/src/ReactContext.js | 25 +- packages/react/src/ReactHooks.js | 21 +- packages/shared/ReactTypes.js | 2 - 19 files changed, 123 insertions(+), 720 deletions(-) diff --git a/packages/react-cache/src/ReactCacheOld.js b/packages/react-cache/src/ReactCacheOld.js index 577ec6bb1a40a..77768dfcf2163 100644 --- a/packages/react-cache/src/ReactCacheOld.js +++ b/packages/react-cache/src/ReactCacheOld.js @@ -46,7 +46,7 @@ const ReactCurrentDispatcher = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED .ReactCurrentDispatcher; -function readContext(Context, observedBits) { +function readContext(Context) { const dispatcher = ReactCurrentDispatcher.current; if (dispatcher === null) { throw new Error( @@ -55,7 +55,7 @@ function readContext(Context, observedBits) { 'lifecycle methods.', ); } - return dispatcher.readContext(Context, observedBits); + return dispatcher.readContext(Context); } function identityHashFn(input) { diff --git a/packages/react-debug-tools/src/ReactDebugHooks.js b/packages/react-debug-tools/src/ReactDebugHooks.js index eb7a8f6d4ef14..d78f629374846 100644 --- a/packages/react-debug-tools/src/ReactDebugHooks.js +++ b/packages/react-debug-tools/src/ReactDebugHooks.js @@ -109,18 +109,12 @@ function getCacheForType(resourceType: () => T): T { invariant(false, 'Not implemented.'); } -function readContext( - context: ReactContext, - observedBits: void | number | boolean, -): T { +function readContext(context: ReactContext): T { // For now we don't expose readContext usage in the hooks debugging info. return context._currentValue; } -function useContext( - context: ReactContext, - observedBits: void | number | boolean, -): T { +function useContext(context: ReactContext): T { hookLog.push({ primitive: 'Context', stackError: new Error(), diff --git a/packages/react-devtools-shared/src/devtools/cache.js b/packages/react-devtools-shared/src/devtools/cache.js index 573f666402717..cc51b31861c12 100644 --- a/packages/react-devtools-shared/src/devtools/cache.js +++ b/packages/react-devtools-shared/src/devtools/cache.js @@ -61,7 +61,7 @@ const Rejected = 2; const ReactCurrentDispatcher = (React: any) .__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentDispatcher; -function readContext(Context, observedBits) { +function readContext(Context) { const dispatcher = ReactCurrentDispatcher.current; if (dispatcher === null) { throw new Error( @@ -70,7 +70,7 @@ function readContext(Context, observedBits) { 'lifecycle methods.', ); } - return dispatcher.readContext(Context, observedBits); + return dispatcher.readContext(Context); } const CacheContext = createContext(null); diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationHooks-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationHooks-test.js index 3014ecd810d20..659a408e6750f 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationHooks-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationHooks-test.js @@ -736,17 +736,6 @@ describe('ReactDOMServerHooks', () => { }, ); - itRenders('warns when bitmask is passed to useContext', async render => { - const Context = React.createContext('Hi'); - - function Foo() { - return {useContext(Context, 1)}; - } - - const domNode = await render(, 1); - expect(domNode.textContent).toBe('Hi'); - }); - describe('useDebugValue', () => { itRenders('is a noop', async render => { function Counter(props) { @@ -760,11 +749,11 @@ describe('ReactDOMServerHooks', () => { }); describe('readContext', () => { - function readContext(Context, observedBits) { + function readContext(Context) { const dispatcher = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED .ReactCurrentDispatcher.current; - return dispatcher.readContext(Context, observedBits); + return dispatcher.readContext(Context); } itRenders( diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationNewContext-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationNewContext-test.js index 338014e66a7c3..cbba195910459 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationNewContext-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationNewContext-test.js @@ -161,11 +161,11 @@ describe('ReactDOMServerIntegration', () => { }); itRenders('readContext() in different components', async render => { - function readContext(Ctx, observedBits) { + function readContext(Ctx) { const dispatcher = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED .ReactCurrentDispatcher.current; - return dispatcher.readContext(Ctx, observedBits); + return dispatcher.readContext(Ctx); } class Cls extends React.Component { diff --git a/packages/react-dom/src/server/ReactPartialRendererHooks.js b/packages/react-dom/src/server/ReactPartialRendererHooks.js index 50edb72c2844a..aeda6e72136f3 100644 --- a/packages/react-dom/src/server/ReactPartialRendererHooks.js +++ b/packages/react-dom/src/server/ReactPartialRendererHooks.js @@ -219,10 +219,7 @@ function getCacheForType(resourceType: () => T): T { invariant(false, 'Not implemented.'); } -function readContext( - context: ReactContext, - observedBits: void | number | boolean, -): T { +function readContext(context: ReactContext): T { const threadID = currentPartialRenderer.threadID; validateContextBounds(context, threadID); if (__DEV__) { @@ -238,10 +235,7 @@ function readContext( return context[threadID]; } -function useContext( - context: ReactContext, - observedBits: void | number | boolean, -): T { +function useContext(context: ReactContext): T { if (__DEV__) { currentHookNameInDev = 'useContext'; } diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.new.js b/packages/react-reconciler/src/ReactFiberBeginWork.new.js index 9ba666bd548e8..2f4bfe98fb0fe 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.new.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.new.js @@ -160,7 +160,6 @@ import { checkIfContextChanged, readContext, prepareToReadContext, - calculateChangedBits, scheduleWorkOnParentPath, } from './ReactFiberNewContext.new'; import {renderWithHooks, bailoutHooks} from './ReactFiberHooks.new'; @@ -221,7 +220,7 @@ import { restoreSpawnedCachePool, getOffscreenDeferredCachePool, } from './ReactFiberCacheComponent.new'; -import {MAX_SIGNED_31_BIT_INT} from './MaxInts'; +import is from 'shared/objectIs'; import {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev'; @@ -795,12 +794,7 @@ function updateCacheComponent( pushCacheProvider(workInProgress, nextCache); if (nextCache !== prevState.cache) { // This cache refreshed. Propagate a context change. - propagateContextChange( - workInProgress, - CacheContext, - MAX_SIGNED_31_BIT_INT, - renderLanes, - ); + propagateContextChange(workInProgress, CacheContext, renderLanes); } } } @@ -1169,12 +1163,7 @@ function updateHostRoot(current, workInProgress, renderLanes) { pushCacheProvider(workInProgress, nextCache); if (nextCache !== prevState.cache) { // The root cache refreshed. - propagateContextChange( - workInProgress, - CacheContext, - MAX_SIGNED_31_BIT_INT, - renderLanes, - ); + propagateContextChange(workInProgress, CacheContext, renderLanes); } } @@ -3011,8 +3000,7 @@ function updateContextProvider( } else { if (oldProps !== null) { const oldValue = oldProps.value; - const changedBits = calculateChangedBits(context, newValue, oldValue); - if (changedBits === 0) { + if (is(oldValue, newValue)) { // No change. Bailout early if children are the same. if ( oldProps.children === newProps.children && @@ -3027,12 +3015,7 @@ function updateContextProvider( } else { // The context value changed. Search for matching consumers and schedule // them to update. - propagateContextChange( - workInProgress, - context, - changedBits, - renderLanes, - ); + propagateContextChange(workInProgress, context, renderLanes); } } } @@ -3090,7 +3073,7 @@ function updateContextConsumer( } prepareToReadContext(workInProgress, renderLanes); - const newValue = readContext(context, newProps.unstable_observedBits); + const newValue = readContext(context); let newChildren; if (__DEV__) { ReactCurrentOwner.current = workInProgress; diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.old.js b/packages/react-reconciler/src/ReactFiberBeginWork.old.js index 822b299d06ca8..9ca4e4afad443 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.old.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.old.js @@ -160,7 +160,6 @@ import { checkIfContextChanged, readContext, prepareToReadContext, - calculateChangedBits, scheduleWorkOnParentPath, } from './ReactFiberNewContext.old'; import {renderWithHooks, bailoutHooks} from './ReactFiberHooks.old'; @@ -221,7 +220,7 @@ import { restoreSpawnedCachePool, getOffscreenDeferredCachePool, } from './ReactFiberCacheComponent.old'; -import {MAX_SIGNED_31_BIT_INT} from './MaxInts'; +import is from 'shared/objectIs'; import {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev'; @@ -795,12 +794,7 @@ function updateCacheComponent( pushCacheProvider(workInProgress, nextCache); if (nextCache !== prevState.cache) { // This cache refreshed. Propagate a context change. - propagateContextChange( - workInProgress, - CacheContext, - MAX_SIGNED_31_BIT_INT, - renderLanes, - ); + propagateContextChange(workInProgress, CacheContext, renderLanes); } } } @@ -1169,12 +1163,7 @@ function updateHostRoot(current, workInProgress, renderLanes) { pushCacheProvider(workInProgress, nextCache); if (nextCache !== prevState.cache) { // The root cache refreshed. - propagateContextChange( - workInProgress, - CacheContext, - MAX_SIGNED_31_BIT_INT, - renderLanes, - ); + propagateContextChange(workInProgress, CacheContext, renderLanes); } } @@ -3011,8 +3000,7 @@ function updateContextProvider( } else { if (oldProps !== null) { const oldValue = oldProps.value; - const changedBits = calculateChangedBits(context, newValue, oldValue); - if (changedBits === 0) { + if (is(oldValue, newValue)) { // No change. Bailout early if children are the same. if ( oldProps.children === newProps.children && @@ -3027,12 +3015,7 @@ function updateContextProvider( } else { // The context value changed. Search for matching consumers and schedule // them to update. - propagateContextChange( - workInProgress, - context, - changedBits, - renderLanes, - ); + propagateContextChange(workInProgress, context, renderLanes); } } } @@ -3090,7 +3073,7 @@ function updateContextConsumer( } prepareToReadContext(workInProgress, renderLanes); - const newValue = readContext(context, newProps.unstable_observedBits); + const newValue = readContext(context); let newChildren; if (__DEV__) { ReactCurrentOwner.current = workInProgress; diff --git a/packages/react-reconciler/src/ReactFiberCacheComponent.new.js b/packages/react-reconciler/src/ReactFiberCacheComponent.new.js index b5ae3ccc611a8..042a8b2efc098 100644 --- a/packages/react-reconciler/src/ReactFiberCacheComponent.new.js +++ b/packages/react-reconciler/src/ReactFiberCacheComponent.new.js @@ -37,7 +37,6 @@ export const CacheContext: ReactContext = enableCache // We don't use Consumer/Provider for Cache components. So we'll cheat. Consumer: (null: any), Provider: (null: any), - _calculateChangedBits: null, // We'll initialize these at the root. _currentValue: (null: any), _currentValue2: (null: any), diff --git a/packages/react-reconciler/src/ReactFiberCacheComponent.old.js b/packages/react-reconciler/src/ReactFiberCacheComponent.old.js index 8882f7dbd2d48..2bc64254d3092 100644 --- a/packages/react-reconciler/src/ReactFiberCacheComponent.old.js +++ b/packages/react-reconciler/src/ReactFiberCacheComponent.old.js @@ -37,7 +37,6 @@ export const CacheContext: ReactContext = enableCache // We don't use Consumer/Provider for Cache components. So we'll cheat. Consumer: (null: any), Provider: (null: any), - _calculateChangedBits: null, // We'll initialize these at the root. _currentValue: (null: any), _currentValue2: (null: any), diff --git a/packages/react-reconciler/src/ReactFiberHooks.new.js b/packages/react-reconciler/src/ReactFiberHooks.new.js index 00afb7daefdd7..9a94ed1536d3e 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.new.js +++ b/packages/react-reconciler/src/ReactFiberHooks.new.js @@ -2191,11 +2191,8 @@ if (__DEV__) { }; HooksDispatcherOnMountInDEV = { - readContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { - return readContext(context, observedBits); + readContext(context: ReactContext): T { + return readContext(context); }, useCallback(callback: T, deps: Array | void | null): T { currentHookNameInDev = 'useCallback'; @@ -2203,13 +2200,10 @@ if (__DEV__) { checkDepsAreArrayDev(deps); return mountCallback(callback, deps); }, - useContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { + useContext(context: ReactContext): T { currentHookNameInDev = 'useContext'; mountHookTypesDev(); - return readContext(context, observedBits); + return readContext(context); }, useEffect( create: () => (() => void) | void, @@ -2326,24 +2320,18 @@ if (__DEV__) { } HooksDispatcherOnMountWithHookTypesInDEV = { - readContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { - return readContext(context, observedBits); + readContext(context: ReactContext): T { + return readContext(context); }, useCallback(callback: T, deps: Array | void | null): T { currentHookNameInDev = 'useCallback'; updateHookTypesDev(); return mountCallback(callback, deps); }, - useContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { + useContext(context: ReactContext): T { currentHookNameInDev = 'useContext'; updateHookTypesDev(); - return readContext(context, observedBits); + return readContext(context); }, useEffect( create: () => (() => void) | void, @@ -2456,24 +2444,18 @@ if (__DEV__) { } HooksDispatcherOnUpdateInDEV = { - readContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { - return readContext(context, observedBits); + readContext(context: ReactContext): T { + return readContext(context); }, useCallback(callback: T, deps: Array | void | null): T { currentHookNameInDev = 'useCallback'; updateHookTypesDev(); return updateCallback(callback, deps); }, - useContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { + useContext(context: ReactContext): T { currentHookNameInDev = 'useContext'; updateHookTypesDev(); - return readContext(context, observedBits); + return readContext(context); }, useEffect( create: () => (() => void) | void, @@ -2586,11 +2568,8 @@ if (__DEV__) { } HooksDispatcherOnRerenderInDEV = { - readContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { - return readContext(context, observedBits); + readContext(context: ReactContext): T { + return readContext(context); }, useCallback(callback: T, deps: Array | void | null): T { @@ -2598,13 +2577,10 @@ if (__DEV__) { updateHookTypesDev(); return updateCallback(callback, deps); }, - useContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { + useContext(context: ReactContext): T { currentHookNameInDev = 'useContext'; updateHookTypesDev(); - return readContext(context, observedBits); + return readContext(context); }, useEffect( create: () => (() => void) | void, @@ -2717,12 +2693,9 @@ if (__DEV__) { } InvalidNestedHooksDispatcherOnMountInDEV = { - readContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { + readContext(context: ReactContext): T { warnInvalidContextAccess(); - return readContext(context, observedBits); + return readContext(context); }, useCallback(callback: T, deps: Array | void | null): T { currentHookNameInDev = 'useCallback'; @@ -2730,14 +2703,11 @@ if (__DEV__) { mountHookTypesDev(); return mountCallback(callback, deps); }, - useContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { + useContext(context: ReactContext): T { currentHookNameInDev = 'useContext'; warnInvalidHookAccess(); mountHookTypesDev(); - return readContext(context, observedBits); + return readContext(context); }, useEffect( create: () => (() => void) | void, @@ -2862,12 +2832,9 @@ if (__DEV__) { } InvalidNestedHooksDispatcherOnUpdateInDEV = { - readContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { + readContext(context: ReactContext): T { warnInvalidContextAccess(); - return readContext(context, observedBits); + return readContext(context); }, useCallback(callback: T, deps: Array | void | null): T { currentHookNameInDev = 'useCallback'; @@ -2875,14 +2842,11 @@ if (__DEV__) { updateHookTypesDev(); return updateCallback(callback, deps); }, - useContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { + useContext(context: ReactContext): T { currentHookNameInDev = 'useContext'; warnInvalidHookAccess(); updateHookTypesDev(); - return readContext(context, observedBits); + return readContext(context); }, useEffect( create: () => (() => void) | void, @@ -3007,12 +2971,9 @@ if (__DEV__) { } InvalidNestedHooksDispatcherOnRerenderInDEV = { - readContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { + readContext(context: ReactContext): T { warnInvalidContextAccess(); - return readContext(context, observedBits); + return readContext(context); }, useCallback(callback: T, deps: Array | void | null): T { @@ -3021,14 +2982,11 @@ if (__DEV__) { updateHookTypesDev(); return updateCallback(callback, deps); }, - useContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { + useContext(context: ReactContext): T { currentHookNameInDev = 'useContext'; warnInvalidHookAccess(); updateHookTypesDev(); - return readContext(context, observedBits); + return readContext(context); }, useEffect( create: () => (() => void) | void, diff --git a/packages/react-reconciler/src/ReactFiberHooks.old.js b/packages/react-reconciler/src/ReactFiberHooks.old.js index 3f60972dcd519..d705a58658d1c 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.old.js +++ b/packages/react-reconciler/src/ReactFiberHooks.old.js @@ -2191,11 +2191,8 @@ if (__DEV__) { }; HooksDispatcherOnMountInDEV = { - readContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { - return readContext(context, observedBits); + readContext(context: ReactContext): T { + return readContext(context); }, useCallback(callback: T, deps: Array | void | null): T { currentHookNameInDev = 'useCallback'; @@ -2203,13 +2200,10 @@ if (__DEV__) { checkDepsAreArrayDev(deps); return mountCallback(callback, deps); }, - useContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { + useContext(context: ReactContext): T { currentHookNameInDev = 'useContext'; mountHookTypesDev(); - return readContext(context, observedBits); + return readContext(context); }, useEffect( create: () => (() => void) | void, @@ -2326,24 +2320,18 @@ if (__DEV__) { } HooksDispatcherOnMountWithHookTypesInDEV = { - readContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { - return readContext(context, observedBits); + readContext(context: ReactContext): T { + return readContext(context); }, useCallback(callback: T, deps: Array | void | null): T { currentHookNameInDev = 'useCallback'; updateHookTypesDev(); return mountCallback(callback, deps); }, - useContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { + useContext(context: ReactContext): T { currentHookNameInDev = 'useContext'; updateHookTypesDev(); - return readContext(context, observedBits); + return readContext(context); }, useEffect( create: () => (() => void) | void, @@ -2456,24 +2444,18 @@ if (__DEV__) { } HooksDispatcherOnUpdateInDEV = { - readContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { - return readContext(context, observedBits); + readContext(context: ReactContext): T { + return readContext(context); }, useCallback(callback: T, deps: Array | void | null): T { currentHookNameInDev = 'useCallback'; updateHookTypesDev(); return updateCallback(callback, deps); }, - useContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { + useContext(context: ReactContext): T { currentHookNameInDev = 'useContext'; updateHookTypesDev(); - return readContext(context, observedBits); + return readContext(context); }, useEffect( create: () => (() => void) | void, @@ -2586,11 +2568,8 @@ if (__DEV__) { } HooksDispatcherOnRerenderInDEV = { - readContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { - return readContext(context, observedBits); + readContext(context: ReactContext): T { + return readContext(context); }, useCallback(callback: T, deps: Array | void | null): T { @@ -2598,13 +2577,10 @@ if (__DEV__) { updateHookTypesDev(); return updateCallback(callback, deps); }, - useContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { + useContext(context: ReactContext): T { currentHookNameInDev = 'useContext'; updateHookTypesDev(); - return readContext(context, observedBits); + return readContext(context); }, useEffect( create: () => (() => void) | void, @@ -2717,12 +2693,9 @@ if (__DEV__) { } InvalidNestedHooksDispatcherOnMountInDEV = { - readContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { + readContext(context: ReactContext): T { warnInvalidContextAccess(); - return readContext(context, observedBits); + return readContext(context); }, useCallback(callback: T, deps: Array | void | null): T { currentHookNameInDev = 'useCallback'; @@ -2730,14 +2703,11 @@ if (__DEV__) { mountHookTypesDev(); return mountCallback(callback, deps); }, - useContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { + useContext(context: ReactContext): T { currentHookNameInDev = 'useContext'; warnInvalidHookAccess(); mountHookTypesDev(); - return readContext(context, observedBits); + return readContext(context); }, useEffect( create: () => (() => void) | void, @@ -2862,12 +2832,9 @@ if (__DEV__) { } InvalidNestedHooksDispatcherOnUpdateInDEV = { - readContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { + readContext(context: ReactContext): T { warnInvalidContextAccess(); - return readContext(context, observedBits); + return readContext(context); }, useCallback(callback: T, deps: Array | void | null): T { currentHookNameInDev = 'useCallback'; @@ -2875,14 +2842,11 @@ if (__DEV__) { updateHookTypesDev(); return updateCallback(callback, deps); }, - useContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { + useContext(context: ReactContext): T { currentHookNameInDev = 'useContext'; warnInvalidHookAccess(); updateHookTypesDev(); - return readContext(context, observedBits); + return readContext(context); }, useEffect( create: () => (() => void) | void, @@ -3007,12 +2971,9 @@ if (__DEV__) { } InvalidNestedHooksDispatcherOnRerenderInDEV = { - readContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { + readContext(context: ReactContext): T { warnInvalidContextAccess(); - return readContext(context, observedBits); + return readContext(context); }, useCallback(callback: T, deps: Array | void | null): T { @@ -3021,14 +2982,11 @@ if (__DEV__) { updateHookTypesDev(); return updateCallback(callback, deps); }, - useContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T { + useContext(context: ReactContext): T { currentHookNameInDev = 'useContext'; warnInvalidHookAccess(); updateHookTypesDev(); - return readContext(context, observedBits); + return readContext(context); }, useEffect( create: () => (() => void) | void, diff --git a/packages/react-reconciler/src/ReactFiberNewContext.new.js b/packages/react-reconciler/src/ReactFiberNewContext.new.js index 29a1eeef8cdd9..9d2484a783971 100644 --- a/packages/react-reconciler/src/ReactFiberNewContext.new.js +++ b/packages/react-reconciler/src/ReactFiberNewContext.new.js @@ -19,7 +19,6 @@ import type {SharedQueue} from './ReactUpdateQueue.new'; import {isPrimaryRenderer} from './ReactFiberHostConfig'; import {createCursor, push, pop} from './ReactFiberStack.new'; -import {MAX_SIGNED_31_BIT_INT} from './MaxInts'; import { ContextProvider, ClassComponent, @@ -58,7 +57,7 @@ if (__DEV__) { let currentlyRenderingFiber: Fiber | null = null; let lastContextDependency: ContextDependency | null = null; -let lastContextWithAllBitsObserved: ReactContext | null = null; +let lastFullyObservedContext: ReactContext | null = null; let isDisallowedContextReadInDEV: boolean = false; @@ -67,7 +66,7 @@ export function resetContextDependencies(): void { // cannot be called outside the render phase. currentlyRenderingFiber = null; lastContextDependency = null; - lastContextWithAllBitsObserved = null; + lastFullyObservedContext = null; if (__DEV__) { isDisallowedContextReadInDEV = false; } @@ -140,33 +139,6 @@ export function popProvider( } } -export function calculateChangedBits( - context: ReactContext, - newValue: T, - oldValue: T, -) { - if (is(oldValue, newValue)) { - // No change - return 0; - } else { - const changedBits = - typeof context._calculateChangedBits === 'function' - ? context._calculateChangedBits(oldValue, newValue) - : MAX_SIGNED_31_BIT_INT; - - if (__DEV__) { - if ((changedBits & MAX_SIGNED_31_BIT_INT) !== changedBits) { - console.error( - 'calculateChangedBits: Expected the return value to be a ' + - '31-bit integer. Instead received: %s', - changedBits, - ); - } - } - return changedBits | 0; - } -} - export function scheduleWorkOnParentPath( parent: Fiber | null, renderLanes: Lanes, @@ -197,7 +169,6 @@ export function scheduleWorkOnParentPath( export function propagateContextChange( workInProgress: Fiber, context: ReactContext, - changedBits: number, renderLanes: Lanes, ): void { if (enableLazyContextPropagation) { @@ -207,24 +178,18 @@ export function propagateContextChange( const forcePropagateEntireTree = true; propagateContextChanges( workInProgress, - [context, changedBits], + [context], renderLanes, forcePropagateEntireTree, ); } else { - propagateContextChange_eager( - workInProgress, - context, - changedBits, - renderLanes, - ); + propagateContextChange_eager(workInProgress, context, renderLanes); } } function propagateContextChange_eager( workInProgress: Fiber, context: ReactContext, - changedBits: number, renderLanes: Lanes, ): void { // Only used by eager implemenation @@ -247,10 +212,7 @@ function propagateContextChange_eager( let dependency = list.firstContext; while (dependency !== null) { // Check if the context matches. - if ( - dependency.context === context && - (dependency.observedBits & changedBits) !== 0 - ) { + if (dependency.context === context) { // Match! Schedule an update on this fiber. if (fiber.tag === ClassComponent) { // Schedule a force update on the work-in-progress. @@ -382,15 +344,11 @@ function propagateContextChanges( // Assigning these to constants to help Flow const dependency = dep; const consumer = fiber; - findContext: for (let i = 0; i < contexts.length; i += 2) { + findContext: for (let i = 0; i < contexts.length; i++) { const context: ReactContext = contexts[i]; - const changedBits: number = contexts[i + 1]; // Check if the context matches. // TODO: Compare selected values to bail out early. - if ( - dependency.context === context && - (dependency.observedBits & changedBits) !== 0 - ) { + if (dependency.context === context) { // Match! Schedule an update on this fiber. // In the lazy implemenation, don't mark a dirty flag on the @@ -549,12 +507,11 @@ function propagateParentContextChanges( const oldValue = oldProps.value; - const changedBits = calculateChangedBits(context, newValue, oldValue); - if (changedBits !== 0) { + if (!is(newValue, oldValue)) { if (contexts !== null) { - contexts.push(context, changedBits); + contexts.push(context); } else { - contexts = [context, changedBits]; + contexts = [context]; } } } @@ -625,7 +582,7 @@ export function prepareToReadContext( ): void { currentlyRenderingFiber = workInProgress; lastContextDependency = null; - lastContextWithAllBitsObserved = null; + lastFullyObservedContext = null; const dependencies = workInProgress.dependencies; if (dependencies !== null) { @@ -646,10 +603,7 @@ export function prepareToReadContext( } } -export function readContext( - context: ReactContext, - observedBits: void | number | boolean, -): T { +export function readContext(context: ReactContext): T { if (__DEV__) { // This warning would fire if you read context inside a Hook like useMemo. // Unlike the class check below, it's not enforced in production for perf. @@ -667,26 +621,11 @@ export function readContext( ? context._currentValue : context._currentValue2; - if (lastContextWithAllBitsObserved === context) { + if (lastFullyObservedContext === context) { // Nothing to do. We already observe everything in this context. - } else if (observedBits === false || observedBits === 0) { - // Do not observe any updates. } else { - let resolvedObservedBits; // Avoid deopting on observable arguments or heterogeneous types. - if ( - typeof observedBits !== 'number' || - observedBits === MAX_SIGNED_31_BIT_INT - ) { - // Observe all updates. - lastContextWithAllBitsObserved = ((context: any): ReactContext); - resolvedObservedBits = MAX_SIGNED_31_BIT_INT; - } else { - resolvedObservedBits = observedBits; - } - const contextItem = { context: ((context: any): ReactContext), - observedBits: resolvedObservedBits, memoizedValue: value, next: null, }; diff --git a/packages/react-reconciler/src/ReactFiberNewContext.old.js b/packages/react-reconciler/src/ReactFiberNewContext.old.js index 0e6ed587b8ddb..c2a1600650119 100644 --- a/packages/react-reconciler/src/ReactFiberNewContext.old.js +++ b/packages/react-reconciler/src/ReactFiberNewContext.old.js @@ -19,7 +19,6 @@ import type {SharedQueue} from './ReactUpdateQueue.old'; import {isPrimaryRenderer} from './ReactFiberHostConfig'; import {createCursor, push, pop} from './ReactFiberStack.old'; -import {MAX_SIGNED_31_BIT_INT} from './MaxInts'; import { ContextProvider, ClassComponent, @@ -58,7 +57,7 @@ if (__DEV__) { let currentlyRenderingFiber: Fiber | null = null; let lastContextDependency: ContextDependency | null = null; -let lastContextWithAllBitsObserved: ReactContext | null = null; +let lastFullyObservedContext: ReactContext | null = null; let isDisallowedContextReadInDEV: boolean = false; @@ -67,7 +66,7 @@ export function resetContextDependencies(): void { // cannot be called outside the render phase. currentlyRenderingFiber = null; lastContextDependency = null; - lastContextWithAllBitsObserved = null; + lastFullyObservedContext = null; if (__DEV__) { isDisallowedContextReadInDEV = false; } @@ -140,33 +139,6 @@ export function popProvider( } } -export function calculateChangedBits( - context: ReactContext, - newValue: T, - oldValue: T, -) { - if (is(oldValue, newValue)) { - // No change - return 0; - } else { - const changedBits = - typeof context._calculateChangedBits === 'function' - ? context._calculateChangedBits(oldValue, newValue) - : MAX_SIGNED_31_BIT_INT; - - if (__DEV__) { - if ((changedBits & MAX_SIGNED_31_BIT_INT) !== changedBits) { - console.error( - 'calculateChangedBits: Expected the return value to be a ' + - '31-bit integer. Instead received: %s', - changedBits, - ); - } - } - return changedBits | 0; - } -} - export function scheduleWorkOnParentPath( parent: Fiber | null, renderLanes: Lanes, @@ -197,7 +169,6 @@ export function scheduleWorkOnParentPath( export function propagateContextChange( workInProgress: Fiber, context: ReactContext, - changedBits: number, renderLanes: Lanes, ): void { if (enableLazyContextPropagation) { @@ -207,24 +178,18 @@ export function propagateContextChange( const forcePropagateEntireTree = true; propagateContextChanges( workInProgress, - [context, changedBits], + [context], renderLanes, forcePropagateEntireTree, ); } else { - propagateContextChange_eager( - workInProgress, - context, - changedBits, - renderLanes, - ); + propagateContextChange_eager(workInProgress, context, renderLanes); } } function propagateContextChange_eager( workInProgress: Fiber, context: ReactContext, - changedBits: number, renderLanes: Lanes, ): void { // Only used by eager implemenation @@ -247,10 +212,7 @@ function propagateContextChange_eager( let dependency = list.firstContext; while (dependency !== null) { // Check if the context matches. - if ( - dependency.context === context && - (dependency.observedBits & changedBits) !== 0 - ) { + if (dependency.context === context) { // Match! Schedule an update on this fiber. if (fiber.tag === ClassComponent) { // Schedule a force update on the work-in-progress. @@ -382,15 +344,11 @@ function propagateContextChanges( // Assigning these to constants to help Flow const dependency = dep; const consumer = fiber; - findContext: for (let i = 0; i < contexts.length; i += 2) { + findContext: for (let i = 0; i < contexts.length; i++) { const context: ReactContext = contexts[i]; - const changedBits: number = contexts[i + 1]; // Check if the context matches. // TODO: Compare selected values to bail out early. - if ( - dependency.context === context && - (dependency.observedBits & changedBits) !== 0 - ) { + if (dependency.context === context) { // Match! Schedule an update on this fiber. // In the lazy implemenation, don't mark a dirty flag on the @@ -549,12 +507,11 @@ function propagateParentContextChanges( const oldValue = oldProps.value; - const changedBits = calculateChangedBits(context, newValue, oldValue); - if (changedBits !== 0) { + if (!is(newValue, oldValue)) { if (contexts !== null) { - contexts.push(context, changedBits); + contexts.push(context); } else { - contexts = [context, changedBits]; + contexts = [context]; } } } @@ -625,7 +582,7 @@ export function prepareToReadContext( ): void { currentlyRenderingFiber = workInProgress; lastContextDependency = null; - lastContextWithAllBitsObserved = null; + lastFullyObservedContext = null; const dependencies = workInProgress.dependencies; if (dependencies !== null) { @@ -646,10 +603,7 @@ export function prepareToReadContext( } } -export function readContext( - context: ReactContext, - observedBits: void | number | boolean, -): T { +export function readContext(context: ReactContext): T { if (__DEV__) { // This warning would fire if you read context inside a Hook like useMemo. // Unlike the class check below, it's not enforced in production for perf. @@ -667,26 +621,11 @@ export function readContext( ? context._currentValue : context._currentValue2; - if (lastContextWithAllBitsObserved === context) { + if (lastFullyObservedContext === context) { // Nothing to do. We already observe everything in this context. - } else if (observedBits === false || observedBits === 0) { - // Do not observe any updates. } else { - let resolvedObservedBits; // Avoid deopting on observable arguments or heterogeneous types. - if ( - typeof observedBits !== 'number' || - observedBits === MAX_SIGNED_31_BIT_INT - ) { - // Observe all updates. - lastContextWithAllBitsObserved = ((context: any): ReactContext); - resolvedObservedBits = MAX_SIGNED_31_BIT_INT; - } else { - resolvedObservedBits = observedBits; - } - const contextItem = { context: ((context: any): ReactContext), - observedBits: resolvedObservedBits, memoizedValue: value, next: null, }; diff --git a/packages/react-reconciler/src/ReactInternalTypes.js b/packages/react-reconciler/src/ReactInternalTypes.js index b1764bed5ac34..e5fd43e6f416e 100644 --- a/packages/react-reconciler/src/ReactInternalTypes.js +++ b/packages/react-reconciler/src/ReactInternalTypes.js @@ -49,7 +49,6 @@ export type ReactPriorityLevel = 99 | 98 | 97 | 96 | 95 | 90; export type ContextDependency = { context: ReactContext, - observedBits: number, next: ContextDependency | null, memoizedValue: T, ... @@ -281,20 +280,14 @@ type Dispatch = A => void; export type Dispatcher = {| getCacheForType?: (resourceType: () => T) => T, - readContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T, + readContext(context: ReactContext): T, useState(initialState: (() => S) | S): [S, Dispatch>], useReducer( reducer: (S, A) => S, initialArg: I, init?: (I) => S, ): [S, Dispatch], - useContext( - context: ReactContext, - observedBits: void | number | boolean, - ): T, + useContext(context: ReactContext): T, useRef(initialValue: T): {|current: T|}, useEffect( create: () => (() => void) | void, diff --git a/packages/react-reconciler/src/__tests__/ReactNewContext-test.js b/packages/react-reconciler/src/__tests__/ReactNewContext-test.js index 43c1e0033c2f3..4f64972715ac4 100644 --- a/packages/react-reconciler/src/__tests__/ReactNewContext-test.js +++ b/packages/react-reconciler/src/__tests__/ReactNewContext-test.js @@ -35,11 +35,11 @@ describe('ReactNewContext', () => { return {type: 'span', children: [], prop, hidden: false}; } - function readContext(Context, observedBits) { + function readContext(Context) { const dispatcher = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED .ReactCurrentDispatcher.current; - return dispatcher.readContext(Context, observedBits); + return dispatcher.readContext(Context); } // Note: This is based on a similar component we use in www. We can delete @@ -62,48 +62,21 @@ describe('ReactNewContext', () => { 'useContext inside function component', Context => function Consumer(props) { - const observedBits = props.unstable_observedBits; - let contextValue; - expect(() => { - contextValue = useContext(Context, observedBits); - }).toErrorDev( - observedBits !== undefined - ? 'useContext() second argument is reserved for future use in React. ' + - `Passing it is not supported. You passed: ${observedBits}.` - : [], - ); + const contextValue = useContext(Context); const render = props.children; return render(contextValue); }, ); sharedContextTests('useContext inside forwardRef component', Context => React.forwardRef(function Consumer(props, ref) { - const observedBits = props.unstable_observedBits; - let contextValue; - expect(() => { - contextValue = useContext(Context, observedBits); - }).toErrorDev( - observedBits !== undefined - ? 'useContext() second argument is reserved for future use in React. ' + - `Passing it is not supported. You passed: ${observedBits}.` - : [], - ); + const contextValue = useContext(Context); const render = props.children; return render(contextValue); }), ); sharedContextTests('useContext inside memoized function component', Context => React.memo(function Consumer(props) { - const observedBits = props.unstable_observedBits; - let contextValue; - expect(() => { - contextValue = useContext(Context, observedBits); - }).toErrorDev( - observedBits !== undefined - ? 'useContext() second argument is reserved for future use in React. ' + - `Passing it is not supported. You passed: ${observedBits}.` - : [], - ); + const contextValue = useContext(Context); const render = props.children; return render(contextValue); }), @@ -113,8 +86,7 @@ describe('ReactNewContext', () => { Context => class Consumer extends React.Component { render() { - const observedBits = this.props.unstable_observedBits; - const contextValue = readContext(Context, observedBits); + const contextValue = readContext(Context); const render = this.props.children; return render(contextValue); } @@ -125,8 +97,7 @@ describe('ReactNewContext', () => { Context => class Consumer extends React.PureComponent { render() { - const observedBits = this.props.unstable_observedBits; - const contextValue = readContext(Context, observedBits); + const contextValue = readContext(Context); const render = this.props.children; return render(contextValue); } @@ -590,227 +561,6 @@ describe('ReactNewContext', () => { ]); }); - it('can skip consumers with bitmask', () => { - const Context = React.createContext({foo: 0, bar: 0}, (a, b) => { - let result = 0; - if (a.foo !== b.foo) { - result |= 0b01; - } - if (a.bar !== b.bar) { - result |= 0b10; - } - return result; - }); - const Consumer = getConsumer(Context); - - function Provider(props) { - return ( - - {props.children} - - ); - } - - function Foo() { - return ( - - {value => { - Scheduler.unstable_yieldValue('Foo'); - return ; - }} - - ); - } - - function Bar() { - return ( - - {value => { - Scheduler.unstable_yieldValue('Bar'); - return ; - }} - - ); - } - - class Indirection extends React.Component { - shouldComponentUpdate() { - return false; - } - render() { - return this.props.children; - } - } - - function App(props) { - return ( - - - - - - - - - - - ); - } - - ReactNoop.render(); - expect(Scheduler).toFlushAndYield(['Foo', 'Bar']); - expect(ReactNoop.getChildren()).toEqual([ - span('Foo: 1'), - span('Bar: 1'), - ]); - - // Update only foo - ReactNoop.render(); - expect(Scheduler).toFlushAndYield(['Foo']); - expect(ReactNoop.getChildren()).toEqual([ - span('Foo: 2'), - span('Bar: 1'), - ]); - - // Update only bar - ReactNoop.render(); - expect(Scheduler).toFlushAndYield(['Bar']); - expect(ReactNoop.getChildren()).toEqual([ - span('Foo: 2'), - span('Bar: 2'), - ]); - - // Update both - ReactNoop.render(); - expect(Scheduler).toFlushAndYield(['Foo', 'Bar']); - expect(ReactNoop.getChildren()).toEqual([ - span('Foo: 3'), - span('Bar: 3'), - ]); - }); - - // @gate !enableLazyContextPropagation - it('can skip parents with bitmask bailout while updating their children', () => { - const Context = React.createContext({foo: 0, bar: 0}, (a, b) => { - let result = 0; - if (a.foo !== b.foo) { - result |= 0b01; - } - if (a.bar !== b.bar) { - result |= 0b10; - } - return result; - }); - const Consumer = getConsumer(Context); - - function Provider(props) { - return ( - - {props.children} - - ); - } - - function Foo(props) { - return ( - - {value => { - Scheduler.unstable_yieldValue('Foo'); - return ( - <> - - {props.children && props.children()} - - ); - }} - - ); - } - - function Bar(props) { - return ( - - {value => { - Scheduler.unstable_yieldValue('Bar'); - return ( - <> - - {props.children && props.children()} - - ); - }} - - ); - } - - class Indirection extends React.Component { - shouldComponentUpdate() { - return false; - } - render() { - return this.props.children; - } - } - - function App(props) { - return ( - - - - {/* Use a render prop so we don't test constant elements. */} - {() => ( - - - {() => ( - - - - )} - - - )} - - - - ); - } - - ReactNoop.render(); - expect(Scheduler).toFlushAndYield(['Foo', 'Bar', 'Foo']); - expect(ReactNoop.getChildren()).toEqual([ - span('Foo: 1'), - span('Bar: 1'), - span('Foo: 1'), - ]); - - // Update only foo - ReactNoop.render(); - expect(Scheduler).toFlushAndYield(['Foo', 'Foo']); - expect(ReactNoop.getChildren()).toEqual([ - span('Foo: 2'), - span('Bar: 1'), - span('Foo: 2'), - ]); - - // Update only bar - ReactNoop.render(); - expect(Scheduler).toFlushAndYield(['Bar']); - expect(ReactNoop.getChildren()).toEqual([ - span('Foo: 2'), - span('Bar: 2'), - span('Foo: 2'), - ]); - - // Update both - ReactNoop.render(); - expect(Scheduler).toFlushAndYield(['Foo', 'Bar', 'Foo']); - expect(ReactNoop.getChildren()).toEqual([ - span('Foo: 3'), - span('Bar: 3'), - span('Foo: 3'), - ]); - }); - it("does not re-render if there's an update in a child", () => { const Context = React.createContext(0); const Consumer = getConsumer(Context); @@ -1063,30 +813,6 @@ describe('ReactNewContext', () => { } describe('Context.Provider', () => { - it('warns if calculateChangedBits returns larger than a 31-bit integer', () => { - const Context = React.createContext( - 0, - (a, b) => Math.pow(2, 32) - 1, // Return 32 bit int - ); - - function App(props) { - return ; - } - - ReactNoop.render(); - expect(Scheduler).toFlushWithoutYielding(); - - // Update - ReactNoop.render(); - - if (gate(flags => !flags.enableLazyContextPropagation)) { - expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev( - 'calculateChangedBits: Expected the return value to be a 31-bit ' + - 'integer. Instead received: 4294967295', - ); - } - }); - it('warns if no value prop provided', () => { const Context = React.createContext(); @@ -1355,6 +1081,9 @@ describe('ReactNewContext', () => { }); describe('readContext', () => { + // Unstable changedBits API was removed. Port this test to context selectors + // once that exists. + // @gate FIXME it('can read the same context multiple times in the same function', () => { const Context = React.createContext({foo: 0, bar: 0, baz: 0}, (a, b) => { let result = 0; @@ -1517,22 +1246,6 @@ describe('ReactNewContext', () => { }); describe('useContext', () => { - it('warns on array.map(useContext)', () => { - const Context = React.createContext(0); - function Foo() { - return [Context].map(useContext); - } - ReactNoop.render(); - expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev( - 'useContext() second argument is reserved for future ' + - 'use in React. Passing it is not supported. ' + - 'You passed: 0.\n\n' + - 'Did you call array.map(useContext)? ' + - 'Calling Hooks inside a loop is not supported. ' + - 'Learn more at https://reactjs.org/link/rules-of-hooks', - ); - }); - it('throws when used in a class component', () => { const Context = React.createContext(0); class Foo extends React.Component { diff --git a/packages/react/src/ReactContext.js b/packages/react/src/ReactContext.js index a3c4243dd0116..41065c13ef067 100644 --- a/packages/react/src/ReactContext.js +++ b/packages/react/src/ReactContext.js @@ -11,30 +11,12 @@ import {REACT_PROVIDER_TYPE, REACT_CONTEXT_TYPE} from 'shared/ReactSymbols'; import type {ReactContext} from 'shared/ReactTypes'; -export function createContext( - defaultValue: T, - calculateChangedBits: ?(a: T, b: T) => number, -): ReactContext { - if (calculateChangedBits === undefined) { - calculateChangedBits = null; - } else { - if (__DEV__) { - if ( - calculateChangedBits !== null && - typeof calculateChangedBits !== 'function' - ) { - console.error( - 'createContext: Expected the optional second argument to be a ' + - 'function. Instead received: %s', - calculateChangedBits, - ); - } - } - } +export function createContext(defaultValue: T): ReactContext { + // TODO: Second argument used to be an optional `calculateChangedBits` + // function. Warn to reserve for future use? const context: ReactContext = { $$typeof: REACT_CONTEXT_TYPE, - _calculateChangedBits: calculateChangedBits, // As a workaround to support multiple concurrent renderers, we categorize // some renderers as primary and others as secondary. We only expect // there to be two concurrent renderers at most: React Native (primary) and @@ -66,7 +48,6 @@ export function createContext( const Consumer = { $$typeof: REACT_CONTEXT_TYPE, _context: context, - _calculateChangedBits: context._calculateChangedBits, }; // $FlowFixMe: Flow complains about not setting a value, which is intentional here Object.defineProperties(Consumer, { diff --git a/packages/react/src/ReactHooks.js b/packages/react/src/ReactHooks.js index d397d8f789f0a..18920be2c8df4 100644 --- a/packages/react/src/ReactHooks.js +++ b/packages/react/src/ReactHooks.js @@ -47,26 +47,9 @@ export function getCacheForType(resourceType: () => T): T { return dispatcher.getCacheForType(resourceType); } -export function useContext( - Context: ReactContext, - unstable_observedBits: number | boolean | void, -): T { +export function useContext(Context: ReactContext): T { const dispatcher = resolveDispatcher(); if (__DEV__) { - if (unstable_observedBits !== undefined) { - console.error( - 'useContext() second argument is reserved for future ' + - 'use in React. Passing it is not supported. ' + - 'You passed: %s.%s', - unstable_observedBits, - typeof unstable_observedBits === 'number' && Array.isArray(arguments[2]) - ? '\n\nDid you call array.map(useContext)? ' + - 'Calling Hooks inside a loop is not supported. ' + - 'Learn more at https://reactjs.org/link/rules-of-hooks' - : '', - ); - } - // TODO: add a more generic warning for invalid values. if ((Context: any)._context !== undefined) { const realContext = (Context: any)._context; @@ -85,7 +68,7 @@ export function useContext( } } } - return dispatcher.useContext(Context, unstable_observedBits); + return dispatcher.useContext(Context); } export function useState( diff --git a/packages/shared/ReactTypes.js b/packages/shared/ReactTypes.js index dc31b998ea31c..19c89f77f9f12 100644 --- a/packages/shared/ReactTypes.js +++ b/packages/shared/ReactTypes.js @@ -49,7 +49,6 @@ export type ReactConsumer = { ref: null, props: { children: (value: T) => ReactNodeList, - unstable_observedBits?: number, ... }, ... @@ -59,7 +58,6 @@ export type ReactContext = { $$typeof: Symbol | number, Consumer: ReactContext, Provider: ReactProviderType, - _calculateChangedBits: ((a: T, b: T) => number) | null, _currentValue: T, _currentValue2: T, _threadCount: number,