Skip to content

Commit

Permalink
Edge case: forbid readContext() during eager reducer
Browse files Browse the repository at this point in the history
  • Loading branch information
gaearon committed Jan 23, 2019
1 parent cfbdf90 commit 223960e
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 0 deletions.
6 changes: 6 additions & 0 deletions packages/react-reconciler/src/ReactFiberHooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -887,7 +887,13 @@ function dispatchAction<S, A>(
if (eagerReducer !== null) {
try {
const currentState: S = (queue.eagerState: any);
// Temporarily clear to forbid calling Hooks in a reducer.
let maybeFiber = currentlyRenderingFiber; // Note: likely null now unlike `fiber`
currentlyRenderingFiber = null;
stashContextDependencies();
const eagerState = eagerReducer(currentState, action);
currentlyRenderingFiber = maybeFiber;
unstashContextDependencies();
// Stash the eagerly computed state, and the reducer used to compute
// it, on the update object. If the reducer hasn't changed by the
// time we enter the render phase, then the eager state can be used
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,41 @@ describe('ReactHooks', () => {
);
});

// Edge case.
it('throws when reading context inside eager useReducer', () => {
const {useState, createContext} = React;
const ThemeContext = createContext('light');

const ReactCurrentDispatcher =
React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
.ReactCurrentDispatcher;

let _setState;
function Fn() {
const [, setState] = useState(0);
_setState = setState;
return null;
}

class Cls extends React.Component {
render() {
_setState(() => {
ReactCurrentDispatcher.current.readContext(ThemeContext);
});
return null;
}
}

expect(() =>
ReactTestRenderer.create(
<React.Fragment>
<Fn />
<Cls />
</React.Fragment>,
),
).toThrow('Context can only be read while React is rendering');
});

it('throws when calling hooks inside useReducer', () => {
const {useReducer, useRef} = React;
function App() {
Expand Down

0 comments on commit 223960e

Please sign in to comment.