vite
vite copied to clipboard
the vite's HMR does not work when I use React.lazy() API for lazyload
Describe the bug
when I use React.lazy(),like this:
// router/index.ts
import React from 'react';
const Home = React.lazy(() => import('../views/Home'));
const About = React.lazy(() => import('../views/About'));
const routes = [
{
path: '/',
exact: true,
component: Home
},
{
path: '/about',
exact: true,
component: About
},
{
path: '/login',
exact: true,
component: React.lazy(() => import('../views/login/login'))
},
{
path: '/form-page',
exact: true,
component: React.lazy(() => import('../views/form-test/form-page'))
},
{
path: '/props-up',
exact: true,
component: React.lazy(() => import('../views/form-test/props-up'))
}
];
export default routes;
supplement!I use react-router-config manage my routes information,like this:
// App.tsx
import { renderRoutes } from 'react-router-config';
import routes from '@/router';
// other code
render(): JSX.Element {
return (
<Router>
<div className={styles.container}>
<div className={styles['title-wraper']}>
<Link to="/">
<span className={styles['link-title']}>Home</span>
</Link>
<span className={styles['link-line']}> | </span>
<Link to="/about">
<span className={styles['link-title']}>About</span>
</Link>
</div>
<Switch>
<React.Suspense fallback={<Loading></Loading>}>
{renderRoutes(routes)}
</React.Suspense>
</Switch>
</div>
</Router>
);
}
when I modify some code in Home.tsx or About.tsx etc,the HMR was not effected.I need refresh the broswer can see my modification.
if I dont use React.lazy() API,the HMR is normal!
Reproduction
I see vite HMR can work,but it nonitor a wrong file.


I modify About.tsx,but vite HMR feed back router/index.ts.
System Info
- OS: win 10
- browser:Chrome 91
- react(react-dom): 17.0.2
- react-router-dom: 5.2.0
- react-router-config: 5.1.1
- vite: 2.4.2
vite.config.ts
import path from 'path';
import { defineConfig } from 'vite';
import reactRefresh from '@vitejs/plugin-react-refresh';
import eslintPlugin from 'vite-plugin-eslint';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [reactRefresh(), eslintPlugin()],
resolve: {
alias: { '@': path.join(__dirname, 'src') }
},
css: {
modules: {
generateScopedName: '[name]__[local]--[hash:base64:5]'
}
}
});
### Used Package Manager
npm
### Logs
```shell
no error!
Validations
- [X] Follow our Code of Conduct
- [X] Read the Contributing Guidelines.
- [X] Read the docs.
- [X] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- [X] Make sure this is a Vite issue and not a framework-specific issue. For example, if it's a Vue SFC related bug, it should likely be reported to https://github.com/vuejs/vue-next instead.
- [X] Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
I can't reproduce this, can you provide a small repro, thanks
Hello @cookiepool. Please provide a minimal reproduction using a GitHub repository or codesandbox. Issues marked with need reproduction will be closed if they have no activity within 3 days.
Same issue, My App is like below code:
const A = lazy(() => import('./pages/A'));
const B = lazy(() => import('./pages/B'));
function App() {
return (
<HashRouter>
<Suspense fallback={<div>loading</div>}>
<Routes>
<Route path="/a" element={<A />} />
<Route path="/b" element={<B />} />
</Routes>
</Suspense>
</HashRouter>
);
}
After use React.lazy, change in Component A (or B) cannot hot reload, but need switch routing.
Same issue, My App is like below code:
const A = lazy(() => import('./pages/A')); const B = lazy(() => import('./pages/B')); function App() { return ( <HashRouter> <Suspense fallback={<div>loading</div>}> <Routes> <Route path="/a" element={<A />} /> <Route path="/b" element={<B />} /> </Routes> </Suspense> </HashRouter> ); }After use React.lazy, change in Component A (or B) cannot hot reload, but need switch routing.
in path '/a', change Component B to hot reload?
maybe you can try this:
if not add this name, i get the same issue with you.
I can't reproduce this, can you provide a small repro, thanks
https://github.com/cookiepool/vite-react-typescript-template you can use this repository!
Hope your team can fix this soon! My team has the same trouble with this!
The issue mainly affects Class Component.Function Component is normal!
The issue mainly affects Class Component.Function Component is normal!
I use Function components, and our app is broken when using lazy import 😅.
I'm using @loadable/component and Function components its worked fine for me.
Hope your team can fix this soon! My team has the same trouble with this!
So do I!
https://github.com/iheyunfei/vite-bug-report-4298
I create a reproduction repo. I both using create-react-app and vite to reproduce the problem successfully. So, I guess this is the problem of upstream react-refresh, not vite.
And the problem only happens on function component, Class Component seems to work.
damn. ~~It looks like if you give function component a name, then both c-r-a and vite example works.~~
// Anonymous direct exports like export default function() {} // are currently ignored.
import React from 'react'
const Foo = () => ( // works
<div>foo</div>
)
export default Foo
import React from 'react'
export default () => ( // doesn't works
<div>foo</div>
)
So, It's definitely not a bug of vite, but an intentional behavior of react facebook/react#21181.
I can't reproduce this either, working examples using lazy throughout the repo https://github.com/NazimHAli/imgur-explorer/blob/master/src/components/App.tsx#L5-L11
import React from 'react' const Foo = () => ( // works <div>foo</div> ) export default Fooimport React from 'react' export default () => ( // doesn't works <div>foo</div> )So, It's definitely not a bug of vite, but an intentional behavior of react facebook/react#21181.
I think using Foo works because component names have to start with a capital letter: https://reactjs.org/docs/components-and-props.html
Note: Always start component names with a capital letter. React treats components starting with lowercase letters as DOM tags. For example,
represents an HTML div tag, but <Welcome /> represents a component and requires Welcome to be in scope.
The issue mainly affects Class Component.Function Component is normal!
I use Function components, and our app is broken when using lazy import 😅.
Have you solve the problem? How to do ?
So, if I understood correctly, a named export works but a default export won't? Does wrapping a component with lazy forget about the naming? I have a setup like this and I'm having trouble with HMR:
// MyComponent.tsx
export const MyComponent: React.FunctionComponent
// App.tsx
const MyComponent = React.lazy(() => import('./components/MyComponent').then(
res => ({ default: res.MyComponent })
)
const App = () => {
return (
<Route path='/' component={MyComponent} />
)
}
Is there some other way I could try to get HMR working correctly?
So, if I understood correctly, a named export works but a default export won't? Does wrapping a component with
lazyforget about the naming? I have a setup like this and I'm having trouble with HMR:
Default exports work - working example:
https://github.com/NazimHAli/imgur-explorer/blob/master/src/components/App.tsx#L5-L13
const Explore = lazy(() => import("@/components/Explore"));
const Footer = lazy(() => import("@/components/Footer"));
const Header = lazy(() => import("@/components/Header"));
const ImageGrid = lazy(() => import("@/components/ImageGrid"));
I see... Well, my setup is a bit more complex with routing, custom providers and hooks. In a nutshell, when HMR is triggered for a component in the lazy loaded path, a hook fails to get a parameter from the URL. It just returns a default value I've set without actually checking the URL again.
If I find the time, I'll try making a small reproduction.
@RubenLaube-Pohto that would make it easier to help troubleshoot :+1:
I'm encountering this issue and can't find any obvious places where i'm not defining a component as a const before export defaulting it.
Any additional input on how people got over this would be appreciated!
I'm using
@loadable/componentand Function components its worked fine for me.
@guibwl
After i used @loadable/component, it works fine。Thank