Skip to content

Commit

Permalink
Fix: Passive effect updates are never sync (facebook#21215)
Browse files Browse the repository at this point in the history
I screwed this up in facebook#21082. Got confused by the < versus > thing again.

The helper functions are annoying, too, because I always forget the
intended order of the arguments. But they're still helpful because when
we refactor the type we only have the change the logic in one place.

Added a regression test.
  • Loading branch information
acdlite authored and koto committed Jun 15, 2021
1 parent 9b06b08 commit 293f473
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 10 deletions.
7 changes: 7 additions & 0 deletions packages/react-reconciler/src/ReactEventPriorities.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ export function higherEventPriority(
return a !== 0 && a < b ? a : b;
}

export function lowerEventPriority(
a: EventPriority,
b: EventPriority,
): EventPriority {
return a === 0 || a > b ? a : b;
}

export function isHigherEventPriority(
a: EventPriority,
b: EventPriority,
Expand Down
7 changes: 7 additions & 0 deletions packages/react-reconciler/src/ReactEventPriorities.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ export function higherEventPriority(
return a !== 0 && a < b ? a : b;
}

export function lowerEventPriority(
a: EventPriority,
b: EventPriority,
): EventPriority {
return a === 0 || a > b ? a : b;
}

export function isHigherEventPriority(
a: EventPriority,
b: EventPriority,
Expand Down
8 changes: 3 additions & 5 deletions packages/react-reconciler/src/ReactFiberWorkLoop.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ import {
IdleEventPriority,
getCurrentUpdatePriority,
setCurrentUpdatePriority,
higherEventPriority,
lowerEventPriority,
lanesToEventPriority,
} from './ReactEventPriorities.new';
import {requestCurrentTransition, NoTransition} from './ReactFiberTransition';
Expand Down Expand Up @@ -2049,10 +2049,8 @@ function commitRootImpl(root, renderPriorityLevel) {
export function flushPassiveEffects(): boolean {
// Returns whether passive effects were flushed.
if (pendingPassiveEffectsLanes !== NoLanes) {
const priority = higherEventPriority(
DefaultEventPriority,
lanesToEventPriority(pendingPassiveEffectsLanes),
);
const renderPriority = lanesToEventPriority(pendingPassiveEffectsLanes);
const priority = lowerEventPriority(DefaultEventPriority, renderPriority);
const prevTransition = ReactCurrentBatchConfig.transition;
const previousPriority = getCurrentUpdatePriority();
try {
Expand Down
8 changes: 3 additions & 5 deletions packages/react-reconciler/src/ReactFiberWorkLoop.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ import {
IdleEventPriority,
getCurrentUpdatePriority,
setCurrentUpdatePriority,
higherEventPriority,
lowerEventPriority,
lanesToEventPriority,
} from './ReactEventPriorities.old';
import {requestCurrentTransition, NoTransition} from './ReactFiberTransition';
Expand Down Expand Up @@ -2049,10 +2049,8 @@ function commitRootImpl(root, renderPriorityLevel) {
export function flushPassiveEffects(): boolean {
// Returns whether passive effects were flushed.
if (pendingPassiveEffectsLanes !== NoLanes) {
const priority = higherEventPriority(
DefaultEventPriority,
lanesToEventPriority(pendingPassiveEffectsLanes),
);
const renderPriority = lanesToEventPriority(pendingPassiveEffectsLanes);
const priority = lowerEventPriority(DefaultEventPriority, renderPriority);
const prevTransition = ReactCurrentBatchConfig.transition;
const previousPriority = getCurrentUpdatePriority();
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
let React;
let ReactNoop;
let Scheduler;
let useState;
let useEffect;

describe('ReactUpdatePriority', () => {
beforeEach(() => {
jest.resetModules();

React = require('react');
ReactNoop = require('react-noop-renderer');
Scheduler = require('scheduler');
useState = React.useState;
useEffect = React.useEffect;
});

function Text({text}) {
Scheduler.unstable_yieldValue(text);
return text;
}

test('setState inside passive effect triggered by sync update should have default priority', async () => {
const root = ReactNoop.createRoot();

function App() {
const [state, setState] = useState(1);
useEffect(() => {
setState(2);
}, []);
return <