Repository: facebook/react
File: packages/react-refresh/src/__tests__/ReactFreshIntegration-test.js (JavaScript)

Code before:
          const {useState} = React;

          export default function App() {
            const [value, setValue] = useState(0);
            React.useEffect(() => {
              Scheduler.log('B mount');
              setValue(1)
              return () => {
                Scheduler.log('B unmount');
              };
            }, []);
            return <h1>B{value}</h1>;
          }
        `);

        // We added an effect, thereby changing Hook order.
        // This causes a remount.
        expect(container.firstChild).not.toBe(el);
        el = container.firstChild;
        expect(el.textContent).toBe('B1');
        assertLog(['B mount']);

        await patch(`
          const {useState} = React;

          export default function App() {
            const [value, setValue] = useState(0);
            React.useEffect(() => {
              Scheduler.log('C mount');
              return () => {
                Scheduler.log('C unmount');
              };
            }, []);
            return <h1>C{value}</h1>;
          }
        `);
        // Same Hooks are called, so state is preserved.
        expect(container.firstChild).toBe(el);
        expect(el.textContent).toBe('C1');

        // Effects are always reset, so effect B was unmounted and C was mounted.
        assertLog(['B unmount', 'C mount']);

        await patch(`
          const {useState} = React;

          export default function App() {
            const [value, setValue] = useState(0);
            return <h1>D{value}</h1>;
          }
        `);

Review comment (suggestion):
This was the only tricky case here as internal act seems to wait for all timers to finish which they never did.

I preserved the 2 properties tested here: effects are unmounted and re-mounted and state is reset when the hook calls change.

Code after:
          export default function App() {
            const [value, setValue] = useState(0);
            React.useEffect(() => {
              Scheduler.log('B mount');
              setValue(1)
              return () => {
                Scheduler.log('B unmount');
              };
            }, []);
            return <h1>B{value}</h1>;
          }
        `);

        // We added an effect, thereby changing Hook order.
        // This causes a remount.
        expect(container.firstChild).not.toBe(el);
        el = container.firstChild;
        expect(el.textContent).toBe('B1');
        assertLog(['B mount']);

        await patch(`
          const {useState} = React;

          export default function App() {
            const [value, setValue] = useState(0);
            React.useEffect(() => {
              Scheduler.log('C mount');
              return () => {
                Scheduler.log('C unmount');
              };
            }, []);
            return <h1>C{value}</h1>;
          }
        `);
        // Same Hooks are called, so state is preserved.
        expect(container.firstChild).toBe(el);
        expect(el.textContent).toBe('C1');

        // Effects are always reset, so effect B was unmounted and C was mounted.
        assertLog(['B unmount', 'C mount']);

        await patch(`
          const {useState} = React;

          export default function App() {
            const [value, setValue] = useState(0);
            return <h1>D{value}</h1>;
          }
        `);
        // Removing the effect changes the signature
        // and causes the component to remount.