From 4d577fd216735384a262cbacdcbc5cda18626497 Mon Sep 17 00:00:00 2001 From: Timothy Yung Date: Mon, 4 Nov 2024 07:46:28 -0800 Subject: [PATCH] More Unit Tests for Refs in Hidden Subtrees (#31404) ## Summary While fixing ref lifecycles in hidden subtrees in https://github.com/facebook/react/pull/31379, @rickhanlonii noticed that we could also add more unit tests for other types of tags to prevent future regressions during code refactors. This PR adds more unit tests in the same vein as those added in https://github.com/facebook/react/pull/31379. ## How did you test this change? Verified unit tests pass: ``` $ yarn $ yarn test ReactFreshIntegration-test.js ``` --- .../__tests__/ReactFreshIntegration-test.js | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/packages/react-refresh/src/__tests__/ReactFreshIntegration-test.js b/packages/react-refresh/src/__tests__/ReactFreshIntegration-test.js index 093d164e70..d851d72eb4 100644 --- a/packages/react-refresh/src/__tests__/ReactFreshIntegration-test.js +++ b/packages/react-refresh/src/__tests__/ReactFreshIntegration-test.js @@ -430,6 +430,131 @@ describe('ReactFreshIntegration', () => { await patch(code); }); + // @gate __DEV__ && enableActivity + it('ignores ref for functional component in hidden subtree', async () => { + const code = ` + import {unstable_Activity as Activity} from 'react'; + + // Avoid creating a new component on Fast Refresh. + global.A = global.A ?? function A() { + return
; + } + const A = global.A; + + function hiddenRef() { + throw new Error('Unexpected hiddenRef() invocation.'); + } + + export default function App() { + return ( + + + + ); + }; + `; + + await render(code); + await patch(code); + }); + + // @gate __DEV__ && enableActivity + it('ignores ref for ref forwarding component in hidden subtree', async () => { + const code = ` + import { + forwardRef, + unstable_Activity as Activity, + } from 'react'; + + // Avoid creating a new component on Fast Refresh. + global.A = global.A ?? forwardRef(function A(props, ref) { + return
; + }); + const A = global.A; + + function hiddenRef() { + throw new Error('Unexpected hiddenRef() invocation.'); + } + + export default function App() { + return ( + + + + ); + }; + `; + + await render(code); + await patch(code); + }); + + // @gate __DEV__ && enableActivity + it('ignores ref for simple memo component in hidden subtree', async () => { + const code = ` + import { + memo, + unstable_Activity as Activity, + } from 'react'; + + // Avoid creating a new component on Fast Refresh. + global.A = global.A ?? memo(function A() { + return
; + }); + const A = global.A; + + function hiddenRef() { + throw new Error('Unexpected hiddenRef() invocation.'); + } + + export default function App() { + return ( + + + + ); + }; + `; + + await render(code); + await patch(code); + }); + + // @gate __DEV__ && enableActivity + it('ignores ref for memo component in hidden subtree', async () => { + // A custom compare function means this won't use SimpleMemoComponent. + const code = ` + import { + memo, + unstable_Activity as Activity, + } from 'react'; + + // Avoid creating a new component on Fast Refresh. + global.A = global.A ?? memo( + function A() { + return
; + }, + () => false, + ); + const A = global.A; + + function hiddenRef() { + throw new Error('Unexpected hiddenRef() invocation.'); + } + + export default function App() { + return ( + + + + ); + }; + `; + + await render(code); + await patch(code); + }); + it('reloads HOCs if they return functions', async () => { if (__DEV__) { await render(`