Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[react] HMR not working with HOC #21

Closed
7 tasks done
marovargovcik opened this issue Jan 6, 2022 · 11 comments · Fixed by #79
Closed
7 tasks done

[react] HMR not working with HOC #21

marovargovcik opened this issue Jan 6, 2022 · 11 comments · Fixed by #79
Labels
feat: hmr p3-minor-bug 🔨 An edge case that only affects very specific usage (priority)

Comments

@marovargovcik
Copy link

marovargovcik commented Jan 6, 2022

Describe the bug

Description

There is a very odd behavior in my project with HMR not updating what the browser is displaying after editing a component.

  • I have a page component About in src/About.tsx that is used as an element for react-router <Route> in src/App.tsx.
  • This page component About is also wrapped with HOC withRandom from src/withRandom.tsx.
  • A Component defined in the same src/About.tsx file is wrapped with HOC withCounter from src/withCounter.tsx and used as one of children of About component

This combination makes HMR not working as expected because any editing to About component is not updating what is being displayed by the browser.

Findings

Updating <h1>original text</h1> in About component does not update the text displayed in the browser.

const Component = memo(() => (
  <div style={{ border: '1px solid black', padding: '8px' }}>
    <b>This is component defined in about.tsx</b>
  </div>
));

const ComponentWithCounter = withCounter('You are finally awake.', Component);

const About = withRandom(
  'One does not simply reproduce a bug in isolated environment',
  memo(() => {
    return (
      <>
        <b>This is about component</b>
        <div style={{ border: '1px solid blue', padding: '8px' }}>
          <ComponentWithCounter>
            {({ decrement, increment }) => (
              <>
                <button onClick={increment} type='button'>
                  +
                </button>
                <button onClick={decrement} type='button'>
                  -
                </button>
              </>
            )}
          </ComponentWithCounter>
          <h1>original text</h1>
        </div>
      </>
    );
  })
);

But after removing/commenting out anything related to withCounter HOC About component reacts to changes as it should:

import { memo } from 'react';

// import { withCounter } from '@/withCounter';
import { withRandom } from '@/withRandom';

// const Component = memo(() => (
//   <div style={{ border: '1px solid black', padding: '8px' }}>
//     <b>This is component defined in about.tsx</b>
//   </div>
// ));

// const ComponentWithCounter = withCounter('You are finally awake.', Component);

const About = withRandom(
  'One does not simply reproduce a bug in isolated environment',
  memo(() => {
    return (
      <>
        <b>This is about component</b>
        <div style={{ border: '1px solid blue', padding: '8px' }}>
          {/* <ComponentWithCounter>
            {({ decrement, increment }) => (
              <>
                <button onClick={increment} type='button'>
                  +
                </button>
                <button onClick={decrement} type='button'>
                  -
                </button>
              </>
            )}
          </ComponentWithCounter> */}
          <h1>original text - changed!</h1>
        </div>
      </>
    );
  })
);

Same goes for removing/commenting out anything related to withRandom:

import { memo } from 'react';

import { withCounter } from '@/withCounter';

const Component = memo(() => (
  <div style={{ border: '1px solid black', padding: '8px' }}>
    <b>This is component defined in about.tsx</b>
  </div>
));

const ComponentWithCounter = withCounter('You are finally awake.', Component);

const About = memo(() => {
  return (
    <>
      <b>This is about component</b>
      <div style={{ border: '1px solid blue', padding: '8px' }}>
        <ComponentWithCounter>
          {({ decrement, increment }) => (
            <>
              <button onClick={increment} type='button'>
                +
              </button>
              <button onClick={decrement} type='button'>
                -
              </button>
            </>
          )}
        </ComponentWithCounter>
        <h1>original text</h1>
      </div>
    </>
  );
});

However I see changes in network tab - the browser just does not update for some reason:

Steps to reproduce

  1. Open the provided reproduction case
  2. Start vite (if it is not already running) with npm run vite:start
  3. in src/About.tsx edit text in <h1> tag of About component
  4. Browser should be updated with new text that was just edited in the previous step but it isn't

Reproduction

https://stackblitz.com/edit/node-tqfxtx?file=src%2FAbout.tsx

System Info

System:
    OS: Linux 5.10 Ubuntu 20.04.3 LTS (Focal Fossa)
    CPU: (16) x64 AMD Ryzen 9 5900HX with Radeon Graphics
    Memory: 1.73 GB / 7.47 GB
    Container: Yes
    Shell: 5.0.17 - /bin/bash
Binaries:
    Node: 16.13.1 - ~/.nvm/versions/node/v16.13.1/bin/node
    npm: 8.2.0 - ~/.nvm/versions/node/v16.13.1/bin/npm
npmPackages:
    @vitejs/plugin-react: ^1.1.4 => 1.1.4 
    vite: ^2.7.10 => 2.7.10

Used Package Manager

npm

Logs

[vite] hot updated: /src/About.tsx

Validations

@NMinhNguyen
Copy link

HOCs are actually known to be unhandled by Fast Refresh (if they return class components): https://nextjs.org/docs/basic-features/fast-refresh#limitations

@Niputi Niputi closed this as completed Jan 12, 2022
@marovargovcik
Copy link
Author

marovargovcik commented Jan 12, 2022

I believe this was closed without a good reason. The HOC in my reproduction link is:

  1. not returning class based component
  2. the link you sent is talking about not preserving local state of the component after being hot refreshed (updated) and not about the component not being refreshed (updated) at all

@Niputi Niputi reopened this Jan 12, 2022
@JulienGrv
Copy link

JulienGrv commented Jan 14, 2022

I am having a very similar issue and I couldn't find the root cause. I'm also using the react-plugin. Downgrading to older version didn't help. Only the html head is being refreshed but body ignored. Really strange. All I can do is manually refresh with F5

@DKBoston15
Copy link

I am having the same issue here and haven't been able to find a solution.

@JulienGrv
Copy link

I don't know what I did but the problem is gone now from my side. I regularly update so maybe that's the reason. I was never able to determine the root cause.

@DKBoston15
Copy link

I don't know what I did but the problem is gone now from my side. I regularly update so maybe that's the reason. I was never able to determine the root cause.

I figured mine out seconds after posting, just a lack of a capital letter in the import that my editor missed.

@sapphi-red
Copy link
Member

I confirmed this still does not work. (Vite 4.0.2 + plugin-react 3.0.0)
https://stackblitz.com/edit/node-w8ab1b?file=src%2FApp.tsx

If I changed any of the following parts, it starts working:

  • remove memo from simpleHOC
  • remove Component variable or change () => <b>foo</b> to <b>foo</b>
  • remove the first argument from simpleHOC

@ArnaudBarre
Copy link
Member

This issue will be fixed by #79. Waiting for Vite 4.1 to enable this change

@marovargovcik
Copy link
Author

@ArnaudBarre Amazing! Thank you for your work.

@ArnaudBarre
Copy link
Member

I will release a 3.1-beta version in the next hour with you want to try

@Looskie
Copy link

Looskie commented Jan 25, 2023

great work!

@github-actions github-actions bot locked and limited conversation to collaborators Feb 9, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feat: hmr p3-minor-bug 🔨 An edge case that only affects very specific usage (priority)
Projects
None yet
8 participants