diff --git a/packages/react-devtools-shared/src/__tests__/console-test.js b/packages/react-devtools-shared/src/__tests__/console-test.js
index e2674b10f3526..e8f5376c7bf2e 100644
--- a/packages/react-devtools-shared/src/__tests__/console-test.js
+++ b/packages/react-devtools-shared/src/__tests__/console-test.js
@@ -625,6 +625,147 @@ describe('console', () => {
expect(mockGroupCollapsed.mock.calls[0][0]).toBe('groupCollapsed');
});
+ it('should double log from useMemo if hideConsoleLogsInStrictMode is disabled in Strict mode', () => {
+ global.__REACT_DEVTOOLS_APPEND_COMPONENT_STACK__ = false;
+ global.__REACT_DEVTOOLS_HIDE_CONSOLE_LOGS_IN_STRICT_MODE__ = false;
+
+ const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
+
+ function App() {
+ React.useMemo(() => {
+ fakeConsole.log('log');
+ fakeConsole.warn('warn');
+ fakeConsole.error('error');
+ fakeConsole.info('info');
+ fakeConsole.group('group');
+ fakeConsole.groupCollapsed('groupCollapsed');
+ }, []);
+ return
;
+ }
+
+ act(() =>
+ root.render(
+
+
+ ,
+ ),
+ );
+ expect(mockLog.mock.calls[0]).toHaveLength(1);
+ expect(mockLog.mock.calls[0][0]).toBe('log');
+ expect(mockLog.mock.calls[1]).toEqual([
+ '%c%s',
+ `color: ${process.env.DARK_MODE_DIMMED_LOG_COLOR}`,
+ 'log',
+ ]);
+
+ expect(mockWarn).toHaveBeenCalledTimes(2);
+ expect(mockWarn.mock.calls[0]).toHaveLength(1);
+ expect(mockWarn.mock.calls[0][0]).toBe('warn');
+ expect(mockWarn.mock.calls[1]).toHaveLength(3);
+ expect(mockWarn.mock.calls[1]).toEqual([
+ '%c%s',
+ `color: ${process.env.DARK_MODE_DIMMED_WARNING_COLOR}`,
+ 'warn',
+ ]);
+
+ expect(mockError).toHaveBeenCalledTimes(2);
+ expect(mockError.mock.calls[0]).toHaveLength(1);
+ expect(mockError.mock.calls[0][0]).toBe('error');
+ expect(mockError.mock.calls[1]).toHaveLength(3);
+ expect(mockError.mock.calls[1]).toEqual([
+ '%c%s',
+ `color: ${process.env.DARK_MODE_DIMMED_ERROR_COLOR}`,
+ 'error',
+ ]);
+
+ expect(mockInfo).toHaveBeenCalledTimes(2);
+ expect(mockInfo.mock.calls[0]).toHaveLength(1);
+ expect(mockInfo.mock.calls[0][0]).toBe('info');
+ expect(mockInfo.mock.calls[1]).toHaveLength(3);
+ expect(mockInfo.mock.calls[1]).toEqual([
+ '%c%s',
+ `color: ${process.env.DARK_MODE_DIMMED_LOG_COLOR}`,
+ 'info',
+ ]);
+
+ expect(mockGroup).toHaveBeenCalledTimes(2);
+ expect(mockGroup.mock.calls[0]).toHaveLength(1);
+ expect(mockGroup.mock.calls[0][0]).toBe('group');
+ expect(mockGroup.mock.calls[1]).toHaveLength(3);
+ expect(mockGroup.mock.calls[1]).toEqual([
+ '%c%s',
+ `color: ${process.env.DARK_MODE_DIMMED_LOG_COLOR}`,
+ 'group',
+ ]);
+
+ expect(mockGroupCollapsed).toHaveBeenCalledTimes(2);
+ expect(mockGroupCollapsed.mock.calls[0]).toHaveLength(1);
+ expect(mockGroupCollapsed.mock.calls[0][0]).toBe('groupCollapsed');
+ expect(mockGroupCollapsed.mock.calls[1]).toHaveLength(3);
+ expect(mockGroupCollapsed.mock.calls[1]).toEqual([
+ '%c%s',
+ `color: ${process.env.DARK_MODE_DIMMED_LOG_COLOR}`,
+ 'groupCollapsed',
+ ]);
+ });
+
+ it('should not double log from useMemo fns if hideConsoleLogsInStrictMode is enabled in Strict mode', () => {
+ global.__REACT_DEVTOOLS_APPEND_COMPONENT_STACK__ = false;
+ global.__REACT_DEVTOOLS_HIDE_CONSOLE_LOGS_IN_STRICT_MODE__ = true;
+
+ const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
+
+ function App() {
+ React.useMemo(() => {
+ console.log(
+ 'CALL',
+ global.__REACT_DEVTOOLS_HIDE_CONSOLE_LOGS_IN_STRICT_MODE__,
+ );
+ fakeConsole.log('log');
+ fakeConsole.warn('warn');
+ fakeConsole.error('error');
+ fakeConsole.info('info');
+ fakeConsole.group('group');
+ fakeConsole.groupCollapsed('groupCollapsed');
+ }, []);
+ return ;
+ }
+
+ act(() =>
+ root.render(
+
+
+ ,
+ ),
+ );
+
+ expect(mockLog).toHaveBeenCalledTimes(1);
+ expect(mockLog.mock.calls[0]).toHaveLength(1);
+ expect(mockLog.mock.calls[0][0]).toBe('log');
+
+ expect(mockWarn).toHaveBeenCalledTimes(1);
+ expect(mockWarn.mock.calls[0]).toHaveLength(1);
+ expect(mockWarn.mock.calls[0][0]).toBe('warn');
+
+ expect(mockError).toHaveBeenCalledTimes(1);
+ expect(mockError.mock.calls[0]).toHaveLength(1);
+ expect(mockError.mock.calls[0][0]).toBe('error');
+
+ expect(mockInfo).toHaveBeenCalledTimes(1);
+ expect(mockInfo.mock.calls[0]).toHaveLength(1);
+ expect(mockInfo.mock.calls[0][0]).toBe('info');
+
+ expect(mockGroup).toHaveBeenCalledTimes(1);
+ expect(mockGroup.mock.calls[0]).toHaveLength(1);
+ expect(mockGroup.mock.calls[0][0]).toBe('group');
+
+ expect(mockGroupCollapsed).toHaveBeenCalledTimes(1);
+ expect(mockGroupCollapsed.mock.calls[0]).toHaveLength(1);
+ expect(mockGroupCollapsed.mock.calls[0][0]).toBe('groupCollapsed');
+ });
+
it('should double log in Strict mode initial render for extension', () => {
global.__REACT_DEVTOOLS_APPEND_COMPONENT_STACK__ = false;
global.__REACT_DEVTOOLS_HIDE_CONSOLE_LOGS_IN_STRICT_MODE__ = false;
diff --git a/packages/react-reconciler/src/ReactFiberHooks.js b/packages/react-reconciler/src/ReactFiberHooks.js
index 742da1577bc71..8e50d3e6d6678 100644
--- a/packages/react-reconciler/src/ReactFiberHooks.js
+++ b/packages/react-reconciler/src/ReactFiberHooks.js
@@ -2636,10 +2636,12 @@ function mountMemo(
): T {
const hook = mountWorkInProgressHook();
const nextDeps = deps === undefined ? null : deps;
+ const nextValue = nextCreate();
if (shouldDoubleInvokeUserFnsInHooksDEV) {
+ setIsStrictModeForDevtools(true);
nextCreate();
+ setIsStrictModeForDevtools(false);
}
- const nextValue = nextCreate();
hook.memoizedState = [nextValue, nextDeps];
return nextValue;
}
@@ -2658,10 +2660,12 @@ function updateMemo(
return prevState[0];
}
}
+ const nextValue = nextCreate();
if (shouldDoubleInvokeUserFnsInHooksDEV) {
+ setIsStrictModeForDevtools(true);
nextCreate();
+ setIsStrictModeForDevtools(false);
}
- const nextValue = nextCreate();
hook.memoizedState = [nextValue, nextDeps];
return nextValue;
}