Skip to content

Commit 5fce648

Browse files
authored
Revert "Disallow reading context during useMemo etc" (#14651)
* Revert "Add test coverage for readContext() on the server (#14649)" This reverts commit fe2ecd2. * Revert "Warn about incorrect use of useImperativeHandle() (#14647)" This reverts commit 8f45a7f. * Revert "Disallow reading context during useMemo etc (#14648)" This reverts commit 1fcbd22.
1 parent fe2ecd2 commit 5fce648

File tree

4 files changed

+12
-110
lines changed

4 files changed

+12
-110
lines changed

Diff for: packages/react-reconciler/src/ReactFiberClassComponent.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
import ReactStrictModeWarnings from './ReactStrictModeWarnings';
2121
import {isMounted} from 'react-reconciler/reflection';
2222
import {get as getInstance, set as setInstance} from 'shared/ReactInstanceMap';
23+
import ReactSharedInternals from 'shared/ReactSharedInternals';
2324
import shallowEqual from 'shared/shallowEqual';
2425
import getComponentName from 'shared/getComponentName';
2526
import invariant from 'shared/invariant';
@@ -47,14 +48,20 @@ import {
4748
hasContextChanged,
4849
emptyContextObject,
4950
} from './ReactFiberContext';
50-
import {readContext} from './ReactFiberNewContext';
5151
import {
5252
requestCurrentTime,
5353
computeExpirationForFiber,
5454
scheduleWork,
5555
flushPassiveEffects,
5656
} from './ReactFiberScheduler';
5757

58+
const ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;
59+
60+
function readContext(contextType: any): any {
61+
const dispatcher = ReactCurrentDispatcher.current;
62+
return dispatcher.readContext(contextType);
63+
}
64+
5865
const fakeInternalInstance = {};
5966
const isArray = Array.isArray;
6067

Diff for: packages/react-reconciler/src/ReactFiberDispatcher.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
* @flow
88
*/
99

10+
import {readContext} from './ReactFiberNewContext';
1011
import {
11-
readContext,
1212
useCallback,
1313
useContext,
1414
useEffect,

Diff for: packages/react-reconciler/src/ReactFiberHooks.js

+3-26
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import type {HookEffectTag} from './ReactHookEffectTags';
1414

1515
import {NoWork} from './ReactFiberExpirationTime';
1616
import {enableHooks} from 'shared/ReactFeatureFlags';
17-
import {readContext as readContextWithoutCheck} from './ReactFiberNewContext';
17+
import {readContext} from './ReactFiberNewContext';
1818
import {
1919
Update as UpdateEffect,
2020
Passive as PassiveEffect,
@@ -284,7 +284,7 @@ export function resetHooks(): void {
284284

285285
// This is used to reset the state of this module when a component throws.
286286
// It's also called inside mountIndeterminateComponent if we determine the
287-
// component is a module-style component, and also in readContext() above.
287+
// component is a module-style component.
288288
renderExpirationTime = NoWork;
289289
currentlyRenderingFiber = null;
290290

@@ -394,7 +394,7 @@ export function useContext<T>(
394394
// Ensure we're in a function component (class components support only the
395395
// .unstable_read() form)
396396
resolveCurrentlyRenderingFiber();
397-
return readContextWithoutCheck(context, observedBits);
397+
return readContext(context, observedBits);
398398
}
399399

400400
export function useState<S>(
@@ -785,29 +785,6 @@ export function useMemo<T>(
785785
return nextValue;
786786
}
787787

788-
export function readContext<T>(
789-
context: ReactContext<T>,
790-
observedBits: void | number | boolean,
791-
): T {
792-
// Forbid reading context inside Hooks.
793-
// The outer check tells us whether we're inside a Hook like useMemo().
794-
// However, it would also be true if we're rendering a class.
795-
if (currentlyRenderingFiber === null) {
796-
// The inner check tells us we're currently in renderWithHooks() phase
797-
// rather than, for example, in a class or a context consumer.
798-
// Then we know it should be an error.
799-
if (renderExpirationTime !== NoWork) {
800-
invariant(
801-
false,
802-
'Context can only be read inside the body of a component. ' +
803-
'If you read context inside a Hook like useMemo or useReducer, ' +
804-
'move the call directly into the component body.',
805-
);
806-
}
807-
}
808-
return readContextWithoutCheck(context, observedBits);
809-
}
810-
811788
function dispatchAction<S, A>(
812789
fiber: Fiber,
813790
queue: UpdateQueue<S, A>,

Diff for: packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js

-82
Original file line numberDiff line numberDiff line change
@@ -672,88 +672,6 @@ describe('ReactHooks', () => {
672672
expect(root.toJSON()).toEqual('123');
673673
});
674674

675-
it('throws when reading context inside useMemo', () => {
676-
const {useMemo, createContext} = React;
677-
const ReactCurrentDispatcher =
678-
React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
679-
.ReactCurrentDispatcher;
680-
681-
const ThemeContext = createContext('light');
682-
function App() {
683-
return useMemo(() => {
684-
return ReactCurrentDispatcher.current.readContext(ThemeContext);
685-
}, []);
686-
}
687-
688-
expect(() => ReactTestRenderer.create(<App />)).toThrow(
689-
'Context can only be read inside the body of a component',
690-
);
691-
});
692-
693-
it('throws when reading context inside useEffect', () => {
694-
const {useEffect, createContext} = React;
695-
const ReactCurrentDispatcher =
696-
React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
697-
.ReactCurrentDispatcher;
698-
699-
const ThemeContext = createContext('light');
700-
function App() {
701-
useEffect(() => {
702-
ReactCurrentDispatcher.current.readContext(ThemeContext);
703-
});
704-
return null;
705-
}
706-
707-
const root = ReactTestRenderer.create(<App />);
708-
expect(() => root.update(<App />)).toThrow(
709-
// The exact message doesn't matter, just make sure we don't allow this
710-
"Cannot read property 'readContext' of null",
711-
);
712-
});
713-
714-
it('throws when reading context inside useLayoutEffect', () => {
715-
const {useLayoutEffect, createContext} = React;
716-
const ReactCurrentDispatcher =
717-
React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
718-
.ReactCurrentDispatcher;
719-
720-
const ThemeContext = createContext('light');
721-
function App() {
722-
useLayoutEffect(() => {
723-
ReactCurrentDispatcher.current.readContext(ThemeContext);
724-
});
725-
return null;
726-
}
727-
728-
expect(() => ReactTestRenderer.create(<App />)).toThrow(
729-
// The exact message doesn't matter, just make sure we don't allow this
730-
"Cannot read property 'readContext' of null",
731-
);
732-
});
733-
734-
it('throws when reading context inside useReducer', () => {
735-
const {useReducer, createContext} = React;
736-
const ReactCurrentDispatcher =
737-
React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
738-
.ReactCurrentDispatcher;
739-
740-
const ThemeContext = createContext('light');
741-
function App() {
742-
useReducer(
743-
() => {
744-
ReactCurrentDispatcher.current.readContext(ThemeContext);
745-
},
746-
null,
747-
{},
748-
);
749-
return null;
750-
}
751-
752-
expect(() => ReactTestRenderer.create(<App />)).toThrow(
753-
'Context can only be read inside the body of a component.',
754-
);
755-
});
756-
757675
it('throws when calling hooks inside useReducer', () => {
758676
const {useReducer, useRef} = React;
759677
function App() {

0 commit comments

Comments
 (0)