Skip to content

Commit 35e4250

Browse files
committed
Patch devtools before running useMemo function in strict mode
This fixes a regression facebook#25583 where we stopped patching before calling useMemo function.
1 parent ad720f3 commit 35e4250

File tree

2 files changed

+147
-2
lines changed

2 files changed

+147
-2
lines changed

packages/react-devtools-shared/src/__tests__/console-test.js

+141
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,147 @@ describe('console', () => {
625625
expect(mockGroupCollapsed.mock.calls[0][0]).toBe('groupCollapsed');
626626
});
627627

628+
it('should double log from useMemo if hideConsoleLogsInStrictMode is disabled in Strict mode', () => {
629+
global.__REACT_DEVTOOLS_APPEND_COMPONENT_STACK__ = false;
630+
global.__REACT_DEVTOOLS_HIDE_CONSOLE_LOGS_IN_STRICT_MODE__ = false;
631+
632+
const container = document.createElement('div');
633+
const root = ReactDOMClient.createRoot(container);
634+
635+
function App() {
636+
React.useMemo(() => {
637+
fakeConsole.log('log');
638+
fakeConsole.warn('warn');
639+
fakeConsole.error('error');
640+
fakeConsole.info('info');
641+
fakeConsole.group('group');
642+
fakeConsole.groupCollapsed('groupCollapsed');
643+
}, []);
644+
return <div />;
645+
}
646+
647+
act(() =>
648+
root.render(
649+
<React.StrictMode>
650+
<App />
651+
</React.StrictMode>,
652+
),
653+
);
654+
expect(mockLog.mock.calls[0]).toHaveLength(1);
655+
expect(mockLog.mock.calls[0][0]).toBe('log');
656+
expect(mockLog.mock.calls[1]).toEqual([
657+
'%c%s',
658+
`color: ${process.env.DARK_MODE_DIMMED_LOG_COLOR}`,
659+
'log',
660+
]);
661+
662+
expect(mockWarn).toHaveBeenCalledTimes(2);
663+
expect(mockWarn.mock.calls[0]).toHaveLength(1);
664+
expect(mockWarn.mock.calls[0][0]).toBe('warn');
665+
expect(mockWarn.mock.calls[1]).toHaveLength(3);
666+
expect(mockWarn.mock.calls[1]).toEqual([
667+
'%c%s',
668+
`color: ${process.env.DARK_MODE_DIMMED_WARNING_COLOR}`,
669+
'warn',
670+
]);
671+
672+
expect(mockError).toHaveBeenCalledTimes(2);
673+
expect(mockError.mock.calls[0]).toHaveLength(1);
674+
expect(mockError.mock.calls[0][0]).toBe('error');
675+
expect(mockError.mock.calls[1]).toHaveLength(3);
676+
expect(mockError.mock.calls[1]).toEqual([
677+
'%c%s',
678+
`color: ${process.env.DARK_MODE_DIMMED_ERROR_COLOR}`,
679+
'error',
680+
]);
681+
682+
expect(mockInfo).toHaveBeenCalledTimes(2);
683+
expect(mockInfo.mock.calls[0]).toHaveLength(1);
684+
expect(mockInfo.mock.calls[0][0]).toBe('info');
685+
expect(mockInfo.mock.calls[1]).toHaveLength(3);
686+
expect(mockInfo.mock.calls[1]).toEqual([
687+
'%c%s',
688+
`color: ${process.env.DARK_MODE_DIMMED_LOG_COLOR}`,
689+
'info',
690+
]);
691+
692+
expect(mockGroup).toHaveBeenCalledTimes(2);
693+
expect(mockGroup.mock.calls[0]).toHaveLength(1);
694+
expect(mockGroup.mock.calls[0][0]).toBe('group');
695+
expect(mockGroup.mock.calls[1]).toHaveLength(3);
696+
expect(mockGroup.mock.calls[1]).toEqual([
697+
'%c%s',
698+
`color: ${process.env.DARK_MODE_DIMMED_LOG_COLOR}`,
699+
'group',
700+
]);
701+
702+
expect(mockGroupCollapsed).toHaveBeenCalledTimes(2);
703+
expect(mockGroupCollapsed.mock.calls[0]).toHaveLength(1);
704+
expect(mockGroupCollapsed.mock.calls[0][0]).toBe('groupCollapsed');
705+
expect(mockGroupCollapsed.mock.calls[1]).toHaveLength(3);
706+
expect(mockGroupCollapsed.mock.calls[1]).toEqual([
707+
'%c%s',
708+
`color: ${process.env.DARK_MODE_DIMMED_LOG_COLOR}`,
709+
'groupCollapsed',
710+
]);
711+
});
712+
713+
it('should not double log from useMemo fns if hideConsoleLogsInStrictMode is enabled in Strict mode', () => {
714+
global.__REACT_DEVTOOLS_APPEND_COMPONENT_STACK__ = false;
715+
global.__REACT_DEVTOOLS_HIDE_CONSOLE_LOGS_IN_STRICT_MODE__ = true;
716+
717+
const container = document.createElement('div');
718+
const root = ReactDOMClient.createRoot(container);
719+
720+
function App() {
721+
React.useMemo(() => {
722+
console.log(
723+
'CALL',
724+
global.__REACT_DEVTOOLS_HIDE_CONSOLE_LOGS_IN_STRICT_MODE__,
725+
);
726+
fakeConsole.log('log');
727+
fakeConsole.warn('warn');
728+
fakeConsole.error('error');
729+
fakeConsole.info('info');
730+
fakeConsole.group('group');
731+
fakeConsole.groupCollapsed('groupCollapsed');
732+
}, []);
733+
return <div />;
734+
}
735+
736+
act(() =>
737+
root.render(
738+
<React.StrictMode>
739+
<App />
740+
</React.StrictMode>,
741+
),
742+
);
743+
744+
expect(mockLog).toHaveBeenCalledTimes(1);
745+
expect(mockLog.mock.calls[0]).toHaveLength(1);
746+
expect(mockLog.mock.calls[0][0]).toBe('log');
747+
748+
expect(mockWarn).toHaveBeenCalledTimes(1);
749+
expect(mockWarn.mock.calls[0]).toHaveLength(1);
750+
expect(mockWarn.mock.calls[0][0]).toBe('warn');
751+
752+
expect(mockError).toHaveBeenCalledTimes(1);
753+
expect(mockError.mock.calls[0]).toHaveLength(1);
754+
expect(mockError.mock.calls[0][0]).toBe('error');
755+
756+
expect(mockInfo).toHaveBeenCalledTimes(1);
757+
expect(mockInfo.mock.calls[0]).toHaveLength(1);
758+
expect(mockInfo.mock.calls[0][0]).toBe('info');
759+
760+
expect(mockGroup).toHaveBeenCalledTimes(1);
761+
expect(mockGroup.mock.calls[0]).toHaveLength(1);
762+
expect(mockGroup.mock.calls[0][0]).toBe('group');
763+
764+
expect(mockGroupCollapsed).toHaveBeenCalledTimes(1);
765+
expect(mockGroupCollapsed.mock.calls[0]).toHaveLength(1);
766+
expect(mockGroupCollapsed.mock.calls[0][0]).toBe('groupCollapsed');
767+
});
768+
628769
it('should double log in Strict mode initial render for extension', () => {
629770
global.__REACT_DEVTOOLS_APPEND_COMPONENT_STACK__ = false;
630771
global.__REACT_DEVTOOLS_HIDE_CONSOLE_LOGS_IN_STRICT_MODE__ = false;

packages/react-reconciler/src/ReactFiberHooks.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -2636,10 +2636,12 @@ function mountMemo<T>(
26362636
): T {
26372637
const hook = mountWorkInProgressHook();
26382638
const nextDeps = deps === undefined ? null : deps;
2639+
const nextValue = nextCreate();
26392640
if (shouldDoubleInvokeUserFnsInHooksDEV) {
2641+
setIsStrictModeForDevtools(true);
26402642
nextCreate();
2643+
setIsStrictModeForDevtools(false);
26412644
}
2642-
const nextValue = nextCreate();
26432645
hook.memoizedState = [nextValue, nextDeps];
26442646
return nextValue;
26452647
}
@@ -2658,10 +2660,12 @@ function updateMemo<T>(
26582660
return prevState[0];
26592661
}
26602662
}
2663+
const nextValue = nextCreate();
26612664
if (shouldDoubleInvokeUserFnsInHooksDEV) {
2665+
setIsStrictModeForDevtools(true);
26622666
nextCreate();
2667+
setIsStrictModeForDevtools(false);
26632668
}
2664-
const nextValue = nextCreate();
26652669
hook.memoizedState = [nextValue, nextDeps];
26662670
return nextValue;
26672671
}

0 commit comments

Comments
 (0)