mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
warn if you try to use act() in prod (#16282)
We have behaviour divergence for act() between prod and dev (specifically, act() + concurrent mode does not flush fallbacks in prod. This doesn't affect anyone in OSS yet) We also don't have a good story for writing tests in prod (and what from what I gather, nobody really writes tests in prod mode). We could have wiped out act() in prod builds, except that _we_ ourselves use act() for our tests when we run them in prod mode. This PR is a compromise to all of this. We will log a warning if you try to use act() in prod mode, and we silence it in our test suites.
This commit is contained in:
+23
-2
@@ -27,7 +27,7 @@ function sleep(period) {
|
||||
|
||||
describe('ReactTestUtils.act()', () => {
|
||||
// first we run all the tests with concurrent mode
|
||||
let concurrentRoot;
|
||||
let concurrentRoot = null;
|
||||
function renderConcurrent(el, dom) {
|
||||
concurrentRoot = ReactDOM.unstable_createRoot(dom);
|
||||
concurrentRoot.render(el);
|
||||
@@ -71,7 +71,7 @@ describe('ReactTestUtils.act()', () => {
|
||||
runActTests('legacy sync mode', renderSync, unmountSync, rerenderSync);
|
||||
|
||||
// and then in batched mode
|
||||
let batchedRoot;
|
||||
let batchedRoot = null;
|
||||
function renderBatched(el, dom) {
|
||||
batchedRoot = ReactDOM.unstable_createSyncRoot(dom);
|
||||
batchedRoot.render(el);
|
||||
@@ -791,5 +791,26 @@ function runActTests(label, render, unmount, rerender) {
|
||||
});
|
||||
}
|
||||
});
|
||||
describe('warn in prod mode', () => {
|
||||
it('warns if you try to use act() in prod mode', () => {
|
||||
const spy = spyOnDevAndProd(console, 'error');
|
||||
|
||||
act(() => {});
|
||||
|
||||
if (!__DEV__) {
|
||||
expect(console.error).toHaveBeenCalledTimes(1);
|
||||
expect(console.error.calls.argsFor(0)[0]).toContain(
|
||||
'act(...) is not supported in production builds of React',
|
||||
);
|
||||
} else {
|
||||
expect(console.error).toHaveBeenCalledTimes(0);
|
||||
}
|
||||
|
||||
spy.calls.reset();
|
||||
// does not warn twice
|
||||
act(() => {});
|
||||
expect(console.error).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -74,8 +74,17 @@ function flushWorkAndMicroTasks(onDone: (err: ?Error) => void) {
|
||||
// so we can tell if any async act() calls try to run in parallel.
|
||||
|
||||
let actingUpdatesScopeDepth = 0;
|
||||
let didWarnAboutUsingActInProd = false;
|
||||
|
||||
function act(callback: () => Thenable) {
|
||||
if (!__DEV__) {
|
||||
if (didWarnAboutUsingActInProd === false) {
|
||||
didWarnAboutUsingActInProd = true;
|
||||
console.error(
|
||||
'act(...) is not supported in production builds of React, and might not behave as expected.',
|
||||
);
|
||||
}
|
||||
}
|
||||
let previousActingUpdatesScopeDepth = actingUpdatesScopeDepth;
|
||||
let previousIsSomeRendererActing;
|
||||
let previousIsThisRendererActing;
|
||||
|
||||
@@ -630,8 +630,17 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
|
||||
// so we can tell if any async act() calls try to run in parallel.
|
||||
|
||||
let actingUpdatesScopeDepth = 0;
|
||||
let didWarnAboutUsingActInProd = false;
|
||||
|
||||
function act(callback: () => Thenable) {
|
||||
if (!__DEV__) {
|
||||
if (didWarnAboutUsingActInProd === false) {
|
||||
didWarnAboutUsingActInProd = true;
|
||||
console.error(
|
||||
'act(...) is not supported in production builds of React, and might not behave as expected.',
|
||||
);
|
||||
}
|
||||
}
|
||||
let previousActingUpdatesScopeDepth = actingUpdatesScopeDepth;
|
||||
let previousIsSomeRendererActing;
|
||||
let previousIsThisRendererActing;
|
||||
|
||||
@@ -55,8 +55,17 @@ function flushWorkAndMicroTasks(onDone: (err: ?Error) => void) {
|
||||
// so we can tell if any async act() calls try to run in parallel.
|
||||
|
||||
let actingUpdatesScopeDepth = 0;
|
||||
let didWarnAboutUsingActInProd = false;
|
||||
|
||||
function act(callback: () => Thenable) {
|
||||
if (!__DEV__) {
|
||||
if (didWarnAboutUsingActInProd === false) {
|
||||
didWarnAboutUsingActInProd = true;
|
||||
console.error(
|
||||
'act(...) is not supported in production builds of React, and might not behave as expected.',
|
||||
);
|
||||
}
|
||||
}
|
||||
let previousActingUpdatesScopeDepth = actingUpdatesScopeDepth;
|
||||
let previousIsSomeRendererActing;
|
||||
let previousIsThisRendererActing;
|
||||
|
||||
@@ -25,6 +25,16 @@ module.exports = function shouldIgnoreConsoleError(format, args) {
|
||||
// They are noisy too so we'll try to ignore them.
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
format.indexOf(
|
||||
'act(...) is not supported in production builds of React'
|
||||
) === 0
|
||||
) {
|
||||
// We don't yet support act() for prod builds, and warn for it.
|
||||
// But we'd like to use act() ourselves for prod builds.
|
||||
// Let's ignore the warning and #yolo.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Looks legit
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user