@@ -605,6 +605,86 @@ describe('ReactFreshIntegration', () => {
605605 }
606606 } ) ;
607607
608+ it ( 'does not get confused when component is called early' , ( ) => {
609+ if ( __DEV__ ) {
610+ render ( `
611+ // This isn't really a valid pattern but it's close enough
612+ // to simulate what happens when you call ReactDOM.render
613+ // in the same file. We want to ensure this doesn't confuse
614+ // the runtime.
615+ App();
616+
617+ function App() {
618+ const [x, setX] = useFancyState('X');
619+ const [y, setY] = useFancyState('Y');
620+ return <h1>A{x}{y}</h1>;
621+ };
622+
623+ function useFancyState(initialState) {
624+ // No real Hook calls to avoid triggering invalid call invariant.
625+ // We only want to verify that we can still call this function early.
626+ return initialState;
627+ }
628+
629+ export default App;
630+ ` ) ;
631+ let el = container . firstChild ;
632+ expect ( el . textContent ) . toBe ( 'AXY' ) ;
633+
634+ patch ( `
635+ // This isn't really a valid pattern but it's close enough
636+ // to simulate what happens when you call ReactDOM.render
637+ // in the same file. We want to ensure this doesn't confuse
638+ // the runtime.
639+ App();
640+
641+ function App() {
642+ const [x, setX] = useFancyState('X');
643+ const [y, setY] = useFancyState('Y');
644+ return <h1>B{x}{y}</h1>;
645+ };
646+
647+ function useFancyState(initialState) {
648+ // No real Hook calls to avoid triggering invalid call invariant.
649+ // We only want to verify that we can still call this function early.
650+ return initialState;
651+ }
652+
653+ export default App;
654+ ` ) ;
655+ // Same state variables, so no remount.
656+ expect ( container . firstChild ) . toBe ( el ) ;
657+ expect ( el . textContent ) . toBe ( 'BXY' ) ;
658+
659+ patch ( `
660+ // This isn't really a valid pattern but it's close enough
661+ // to simulate what happens when you call ReactDOM.render
662+ // in the same file. We want to ensure this doesn't confuse
663+ // the runtime.
664+ App();
665+
666+ function App() {
667+ const [y, setY] = useFancyState('Y');
668+ const [x, setX] = useFancyState('X');
669+ return <h1>B{x}{y}</h1>;
670+ };
671+
672+ function useFancyState(initialState) {
673+ // No real Hook calls to avoid triggering invalid call invariant.
674+ // We only want to verify that we can still call this function early.
675+ return initialState;
676+ }
677+
678+ export default App;
679+ ` ) ;
680+ // Hooks were re-ordered. This causes a remount.
681+ // Therefore, Hook calls don't accidentally share state.
682+ expect ( container . firstChild ) . not . toBe ( el ) ;
683+ el = container . firstChild ;
684+ expect ( el . textContent ) . toBe ( 'BXY' ) ;
685+ }
686+ } ) ;
687+
608688 it ( 'does not get confused by Hooks defined inline' , ( ) => {
609689 // This is not a recommended pattern but at least it shouldn't break.
610690 if ( __DEV__ ) {
0 commit comments