mirror of
https://github.com/zebrajr/react.git
synced 2026-01-15 12:15:22 +00:00
Allow flushSync to noop in life cycles but with a warning (#18759)
This commit is contained in:
committed by
GitHub
parent
f342a2399f
commit
53ce0c3452
@@ -127,7 +127,7 @@ describe('ReactDOMFiberAsync', () => {
|
||||
expect(ops).toEqual(['A', 'ABCD']);
|
||||
});
|
||||
|
||||
it('flushSync throws if already performing work', () => {
|
||||
it('flushSync logs an error if already performing work', () => {
|
||||
class Component extends React.Component {
|
||||
componentDidUpdate() {
|
||||
ReactDOM.flushSync(() => {});
|
||||
@@ -140,7 +140,7 @@ describe('ReactDOMFiberAsync', () => {
|
||||
// Initial mount
|
||||
ReactDOM.render(<Component />, container);
|
||||
// Update
|
||||
expect(() => ReactDOM.render(<Component />, container)).toThrow(
|
||||
expect(() => ReactDOM.render(<Component />, container)).toErrorDev(
|
||||
'flushSync was called from inside a lifecycle method',
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1228,14 +1228,17 @@ export function unbatchedUpdates<A, R>(fn: (a: A) => R, a: A): R {
|
||||
}
|
||||
|
||||
export function flushSync<A, R>(fn: A => R, a: A): R {
|
||||
if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {
|
||||
invariant(
|
||||
false,
|
||||
'flushSync was called from inside a lifecycle method. It cannot be ' +
|
||||
'called when React is already rendering.',
|
||||
);
|
||||
}
|
||||
const prevExecutionContext = executionContext;
|
||||
if ((prevExecutionContext & (RenderContext | CommitContext)) !== NoContext) {
|
||||
if (__DEV__) {
|
||||
console.error(
|
||||
'flushSync was called from inside a lifecycle method. React cannot ' +
|
||||
'flush when React is already rendering. Consider moving this call to ' +
|
||||
'a scheduler task or micro task.',
|
||||
);
|
||||
}
|
||||
return fn(a);
|
||||
}
|
||||
executionContext |= BatchedContext;
|
||||
try {
|
||||
return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a));
|
||||
|
||||
@@ -1150,14 +1150,17 @@ export function unbatchedUpdates<A, R>(fn: (a: A) => R, a: A): R {
|
||||
}
|
||||
|
||||
export function flushSync<A, R>(fn: A => R, a: A): R {
|
||||
if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {
|
||||
invariant(
|
||||
false,
|
||||
'flushSync was called from inside a lifecycle method. It cannot be ' +
|
||||
'called when React is already rendering.',
|
||||
);
|
||||
}
|
||||
const prevExecutionContext = executionContext;
|
||||
if ((prevExecutionContext & (RenderContext | CommitContext)) !== NoContext) {
|
||||
if (__DEV__) {
|
||||
console.error(
|
||||
'flushSync was called from inside a lifecycle method. React cannot ' +
|
||||
'flush when React is already rendering. Consider moving this call to ' +
|
||||
'a scheduler task or micro task.',
|
||||
);
|
||||
}
|
||||
return fn(a);
|
||||
}
|
||||
executionContext |= BatchedContext;
|
||||
try {
|
||||
return runWithPriority(ImmediatePriority, fn.bind(null, a));
|
||||
|
||||
@@ -1808,22 +1808,26 @@ describe('ReactHooksWithNoopRenderer', () => {
|
||||
ReactNoop.flushSync(() => {
|
||||
updateCount(props.count);
|
||||
});
|
||||
// This shouldn't flush synchronously.
|
||||
expect(ReactNoop.getChildren()).not.toEqual([
|
||||
span('Count: ' + props.count),
|
||||
]);
|
||||
}, [props.count]);
|
||||
return <Text text={'Count: ' + count} />;
|
||||
}
|
||||
act(() => {
|
||||
ReactNoop.render(<Counter count={0} />, () =>
|
||||
Scheduler.unstable_yieldValue('Sync effect'),
|
||||
);
|
||||
expect(Scheduler).toFlushAndYieldThrough([
|
||||
'Count: (empty)',
|
||||
'Sync effect',
|
||||
]);
|
||||
expect(ReactNoop.getChildren()).toEqual([span('Count: (empty)')]);
|
||||
expect(() => {
|
||||
ReactNoop.flushPassiveEffects();
|
||||
}).toThrow('flushSync was called from inside a lifecycle method');
|
||||
});
|
||||
expect(() =>
|
||||
act(() => {
|
||||
ReactNoop.render(<Counter count={0} />, () =>
|
||||
Scheduler.unstable_yieldValue('Sync effect'),
|
||||
);
|
||||
expect(Scheduler).toFlushAndYieldThrough([
|
||||
'Count: (empty)',
|
||||
'Sync effect',
|
||||
]);
|
||||
expect(ReactNoop.getChildren()).toEqual([span('Count: (empty)')]);
|
||||
}),
|
||||
).toErrorDev('flushSync was called from inside a lifecycle method');
|
||||
expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]);
|
||||
});
|
||||
|
||||
it('unmounts previous effect', () => {
|
||||
|
||||
Reference in New Issue
Block a user