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

HMR breaks when modifying React context provider #3301

Closed
6 tasks done
selrond opened this issue May 7, 2021 · 51 comments · Fixed by #10239
Closed
6 tasks done

HMR breaks when modifying React context provider #3301

selrond opened this issue May 7, 2021 · 51 comments · Fixed by #10239
Labels
feat: hmr p3-minor-bug An edge case that only affects very specific usage (priority)

Comments

@selrond
Copy link

selrond commented May 7, 2021

Describe the bug

Vite HMR breaks when modifying React context provider
Related: vitejs/vite-plugin-react#24

Reproduction

selrond/vite-react-usecontext

System Info

Output of npx envinfo --system --npmPackages vite,@vitejs/plugin-vue --binaries --browsers:

  System:
    OS: macOS 10.15.7
    CPU: (8) x64 Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz
    Memory: 413.26 MB / 16.00 GB
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 15.14.0 - ~/.nvm/versions/node/v15.14.0/bin/node
    Yarn: 1.22.10 - /usr/local/bin/yarn
    npm: 7.7.6 - ~/.nvm/versions/node/v15.14.0/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  Browsers:
    Brave Browser: 89.1.21.76
    Chrome: 90.0.4430.93
    Firefox: 87.0
    Firefox Developer Edition: 89.0
    Safari: 14.0.3
  npmPackages:
    vite: ^2.2.3 => 2.2.4 

Used package manager: npm

Logs


Before submitting the issue, please make sure you do the following

  • Read the Contributing Guidelines.
  • Read the docs.
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
  • Provide a description in this issue that describes the bug.
  • 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.
  • Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
@IgnusG
Copy link

IgnusG commented Aug 29, 2021

In my case the context mechanism behind react seems to break - I get 2 renders of the same component:

  • 1 with the default react context value (even though provider is specified)
  • 1 with the value from the provider

My config for vite is empty so no other plugins can be influencing this. The only thing that helps is restarting vite (simple reload of the website does not work so it must be caching of HMR even on reloads). Disabling HMR entirely server.hmr = false fixes the issue at the cost of no HMR.

After changing more things afterwards I suddenly started getting a weird _s is not defined in the component even with the most barebones context when HMR kicks in after changing anything. (again fixed by restarting vite).

App.tsx:25 Uncaught TypeError: _s is not a function
    at App (App.tsx:25)
    at renderWithHooks (react-dom.development.js:14985)
    at mountIndeterminateComponent (react-dom.development.js:17811)
    at beginWork (react-dom.development.js:19049)
    at HTMLUnknownElement.callCallback2 (react-dom.development.js:3945)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:3994)
    at invokeGuardedCallback (react-dom.development.js:4056)
    at beginWork$1 (react-dom.development.js:23964)
    at performUnitOfWork (react-dom.development.js:22776)
    at workLoopSync (react-dom.development.js:22707)
Debug trace from Vite
$ vite --debug
  vite:config TS + native esm config loaded in 27ms URL {
  href: 'file:///home/some-random-app/packages/app/vite.config.ts',
  origin: 'null',
  protocol: 'file:',
  username: '',
  password: '',
  host: '',
  hostname: '',
  port: '',
  pathname: '/home/some-random-app/packages/app/vite.config.ts',
  search: '',
  searchParams: URLSearchParams {},
  hash: ''
} +0ms
  vite:config using resolved config: {
  vite:config   server: { fs: { strict: undefined, allow: [Array] } },
  vite:config   configFile: '/home/some-random-app/packages/app/vite.config.ts',
  vite:config   configFileDependencies: [ 'vite.config.ts' ],
  vite:config   inlineConfig: {
  vite:config     root: undefined,
  vite:config     base: undefined,
  vite:config     mode: undefined,
  vite:config     configFile: undefined,
  vite:config     logLevel: undefined,
  vite:config     clearScreen: undefined,
  vite:config     server: { fs: [Object] }
  vite:config   },
  vite:config   root: '/home/some-random-app/packages/app',
  vite:config   base: '/',
  vite:config   resolve: { dedupe: undefined, alias: [ [Object], [Object] ] },
  vite:config   publicDir: '/home/some-random-app/packages/app/public',
  vite:config   cacheDir: '/home/some-random-app/packages/app/node_modules/.vite',
  vite:config   command: 'serve',
  vite:config   mode: 'development',
  vite:config   isProduction: false,
  vite:config   plugins: [
  vite:config     'vite:pre-alias',
  vite:config     'alias',
  vite:config     'vite:modulepreload-polyfill',
  vite:config     'vite:resolve',
  vite:config     'vite:html',
  vite:config     'vite:css',
  vite:config     'vite:esbuild',
  vite:config     'vite:json',
  vite:config     'vite:wasm',
  vite:config     'vite:worker',
  vite:config     'vite:asset',
  vite:config     'vite:define',
  vite:config     'vite:css-post',
  vite:config     'vite:client-inject',
  vite:config     'vite:import-analysis'
  vite:config   ],
  vite:config   build: {
  vite:config     target: [ 'es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1' ],
  vite:config     polyfillModulePreload: true,
  vite:config     outDir: 'dist',
  vite:config     assetsDir: 'assets',
  vite:config     assetsInlineLimit: 4096,
  vite:config     cssCodeSplit: true,
  vite:config     sourcemap: false,
  vite:config     rollupOptions: {},
  vite:config     commonjsOptions: { include: [Array], extensions: [Array] },
  vite:config     dynamicImportVarsOptions: { warnOnError: true, exclude: [Array] },
  vite:config     minify: 'terser',
  vite:config     terserOptions: {},
  vite:config     write: true,
  vite:config     emptyOutDir: null,
  vite:config     manifest: false,
  vite:config     lib: false,
  vite:config     ssr: false,
  vite:config     ssrManifest: false,
  vite:config     brotliSize: true,
  vite:config     chunkSizeWarningLimit: 500,
  vite:config     watch: null
  vite:config   },
  vite:config   env: {
  vite:config     VITE_FUZZ_LOCALES: 'true',
  vite:config     BASE_URL: '/',
  vite:config     MODE: 'development',
  vite:config     DEV: true,
  vite:config     PROD: false
  vite:config   },
  vite:config   assetsInclude: [Function: assetsInclude],
  vite:config   logger: {
  vite:config     hasWarned: false,
  vite:config     info: [Function: info],
  vite:config     warn: [Function: warn],
  vite:config     warnOnce: [Function: warnOnce],
  vite:config     error: [Function: error],
  vite:config     clearScreen: [Function: clearScreen],
  vite:config     hasErrorLogged: [Function: hasErrorLogged]
  vite:config   },
  vite:config   createResolver: [Function: createResolver],
  vite:config   optimizeDeps: { esbuildOptions: { keepNames: undefined } }
  vite:config } +5ms
  vite:deps Hash is consistent. Skipping. Use --force to override. +0ms

vite v2.5.1 dev server running at:

Local: http://localhost:3000/
Network: use --host to expose

ready in 166ms.

vite:time 1ms / +0ms
vite:spa-fallback Rewriting GET / to /index.html +0ms
vite:time 17ms /index.html +55ms
vite:resolve 1ms /@vite/client -> /home/some-random-app/node_modules/vite/dist/client/client.mjs +0ms
vite:load 1ms [fs] /@vite/client +0ms
vite:resolve 0ms @vite/env -> /home/some-random-app/node_modules/vite/dist/client/env.mjs +9ms
vite:transform 6ms /@vite/client +0ms
vite:time 13ms /@vite/client +123ms
vite:resolve 1ms /src/main.tsx -> /home/some-random-app/packages/app/src/main.tsx +3ms
vite:load 1ms [fs] /src/main.tsx +11ms
vite:resolve 0ms react -> /home/some-random-app/packages/app/node_modules/.vite/react.js?v=c73c3b06&es-interop +6ms
vite:resolve 0ms /node_modules/.vite/react.js?v=c73c3b06&es-interop -> /home/some-random-app/packages/app/node_modules/.vite/react.js?v=c73c3b06&es-interop +0ms
vite:resolve 0ms react-dom -> /home/some-random-app/packages/app/node_modules/.vite/react-dom.js?v=c73c3b06&es-interop +3ms
vite:resolve 0ms /node_modules/.vite/react-dom.js?v=c73c3b06&es-interop -> /home/some-random-app/packages/app/node_modules/.vite/react-dom.js?v=c73c3b06&es-interop +1ms
vite:resolve 2ms app/src/components/organisms -> /home/some-random-app/packages/app/src/components/organisms/index.ts +3ms
vite:resolve 0ms /src/components/organisms/index.ts -> /home/some-random-app/packages/app/src/components/organisms/index.ts +0ms
vite:resolve 1ms app/src/services/api-client/api-client -> /home/some-random-app/packages/app/src/services/api-client/api-client.ts +1ms
vite:resolve 0ms /src/services/api-client/api-client.ts -> /home/some-random-app/packages/app/src/services/api-client/api-client.ts +0ms
vite:resolve 0ms app/src/services/users/users -> /home/some-random-app/packages/app/src/services/users/users.ts +0ms
vite:resolve 0ms /src/services/users/users.ts -> /home/some-random-app/packages/app/src/services/users/users.ts +0ms
vite:resolve 1ms app/src/services/localization/localization -> /home/some-random-app/packages/app/src/services/localization/localization.ts +1ms
vite:resolve 0ms /src/services/localization/localization.ts -> /home/some-random-app/packages/app/src/services/localization/localization.ts +0ms
vite:resolve 0ms app/src/contexts -> /home/some-random-app/packages/app/src/contexts/index.ts +0ms
vite:resolve 0ms /src/contexts/index.ts -> /home/some-random-app/packages/app/src/contexts/index.ts +0ms
vite:resolve 0ms /node_modules/.vite/react.js?v=c73c3b06 -> /home/some-random-app/packages/app/node_modules/.vite/react.js?v=c73c3b06 +0ms
vite:resolve 0ms /node_modules/.vite/react-dom.js?v=c73c3b06 -> /home/some-random-app/packages/app/node_modules/.vite/react-dom.js?v=c73c3b06 +1ms
vite:transform 15ms /src/main.tsx +18ms
vite:time 18ms /src/main.tsx +18ms
vite:load 0ms [fs] npm: vite +56ms
vite:rewrite 0ms [no imports] /home/some-random-app/node_modules/vite/dist/client/env.mjs
+0ms
vite:transform 0ms npm: vite +42ms
vite:time 2ms npm: vite +41ms
vite:load 0ms [fs] /src/components/organisms/index.ts +9ms
vite:resolve 0ms ./app/App -> /home/some-random-app/packages/app/src/components/organisms/app/App.tsx +53ms
vite:resolve 0ms /src/components/organisms/app/App.tsx -> /home/some-random-app/packages/app/src/components/organisms/app/App.tsx +1ms
vite:transform 3ms /src/components/organisms/index.ts +12ms
vite:time 5ms /src/components/organisms/index.ts +12ms
vite:load 1ms [fs] /src/services/api-client/api-client.ts +6ms
vite:resolve 1ms app/src/batteries/server-client/server-client -> /home/some-random-app/packages/app/src/batteries/server-client/server-client.ts +6ms
vite:resolve 0ms /src/batteries/server-client/server-client.ts -> /home/some-random-app/packages/app/src/batteries/server-client/server-client.ts +0ms
vite:resolve 0ms app/src/batteries/singleton/singleton -> /home/some-random-app/packages/app/src/batteries/singleton/singleton.ts +0ms
vite:resolve 1ms /src/batteries/singleton/singleton.ts -> /home/some-random-app/packages/app/src/batteries/singleton/singleton.ts +1ms
vite:resolve 0ms app/src/config -> /home/some-random-app/packages/app/src/config.ts +0ms
vite:resolve 0ms /src/config.ts -> /home/some-random-app/packages/app/src/config.ts +0ms
vite:transform 5ms /src/services/api-client/api-client.ts +7ms
vite:time 6ms /src/services/api-client/api-client.ts +7ms
vite:load 0ms [fs] /src/services/users/users.ts +7ms
vite:resolve 0ms server/src/api/user/route -> /home/some-random-app/packages/server/src/api/user/route.ts +6ms
vite:resolve 0ms app/src/batteries/state/state -> /home/some-random-app/packages/app/src/batteries/state/state.ts +1ms
vite:resolve 0ms /src/batteries/state/state.ts -> /home/some-random-app/packages/app/src/batteries/state/state.ts +0ms
vite:transform 6ms /src/services/users/users.ts +8ms
vite:time 7ms /src/services/users/users.ts +8ms
vite:load 0ms [fs] /src/services/localization/localization.ts +8ms
vite:resolve 1ms i18next -> /home/some-random-app/packages/app/node_modules/.vite/i18next.js?v=c73c3b06 +6ms
vite:resolve 0ms /node_modules/.vite/i18next.js?v=c73c3b06 -> /home/some-random-app/packages/app/node_modules/.vite/i18next.js?v=c73c3b06 +0ms
vite:resolve 0ms react-i18next -> /home/some-random-app/packages/app/node_modules/.vite/react-i18next.js?v=c73c3b06 +0ms
vite:resolve 0ms /node_modules/.vite/react-i18next.js?v=c73c3b06 -> /home/some-random-app/packages/app/node_modules/.vite/react-i18next.js?v=c73c3b06 +0ms
vite:resolve 0ms i18next-icu -> /home/some-random-app/packages/app/node_modules/.vite/i18next-icu.js?v=c73c3b06 +0ms
vite:resolve 0ms /node_modules/.vite/i18next-icu.js?v=c73c3b06 -> /home/some-random-app/packages/app/node_modules/.vite/i18next-icu.js?v=c73c3b06 +0ms
vite:resolve 0ms i18next-http-backend -> /home/some-random-app/packages/app/node_modules/.vite/i18next-http-backend.js?v=c73c3b06 +0ms
vite:resolve 0ms /node_modules/.vite/i18next-http-backend.js?v=c73c3b06 -> /home/some-random-app/packages/app/node_modules/.vite/i18next-http-backend.js?v=c73c3b06 +1ms
vite:resolve 0ms ./fuzzer -> /home/some-random-app/packages/app/src/services/localization/fuzzer.ts +1ms
vite:resolve 0ms /src/services/localization/fuzzer.ts -> /home/some-random-app/packages/app/src/services/localization/fuzzer.ts +0ms
vite:transform 6ms /src/services/localization/localization.ts +8ms
vite:time 7ms /src/services/localization/localization.ts +8ms
vite:load 0ms [fs] /src/contexts/index.ts +9ms
vite:resolve 0ms ./services/services -> /home/some-random-app/packages/app/src/contexts/services/services.ts +7ms
vite:resolve 0ms /src/contexts/services/services.ts -> /home/some-random-app/packages/app/src/contexts/services/services.ts +0ms
vite:transform 3ms /src/contexts/index.ts +6ms
vite:time 5ms /src/contexts/index.ts +7ms
vite:load 0ms [fs] /src/components/organisms/app/App.tsx +9ms
vite:resolve 0ms app/src/batteries/style/style -> /home/some-random-app/packages/app/src/batteries/style/style.ts +10ms
vite:resolve 1ms /src/batteries/style/style.ts -> /home/some-random-app/packages/app/src/batteries/style/style.ts +1ms
vite:resolve 2ms app/src/main -> /home/some-random-app/packages/app/src/main.tsx +2ms
vite:resolve 1ms daisyui/dist/full.css -> /home/some-random-app/node_modules/daisyui/dist/full.css +1ms
vite:transform 7ms /src/components/organisms/app/App.tsx +14ms
vite:time 9ms /src/components/organisms/app/App.tsx +13ms
vite:load 1ms [fs] /src/batteries/server-client/server-client.ts +21ms
vite:resolve 0ms @trpc/client -> /home/some-random-app/packages/app/node_modules/.vite/@trpc_client.js?v=c73c3b06 +17ms
vite:resolve 0ms /node_modules/.vite/@trpc_client.js?v=c73c3b06 -> /home/some-random-app/packages/app/node_modules/.vite/@trpc_client.js?v=c73c3b06 +0ms
vite:transform 4ms /src/batteries/server-client/server-client.ts +17ms
vite:time 6ms /src/batteries/server-client/server-client.ts +18ms
vite:load 2ms [fs] /src/config.ts +8ms
vite:load 1ms [fs] /src/batteries/singleton/singleton.ts +0ms
vite:transform 1ms /src/config.ts +5ms
vite:time 3ms /src/config.ts +4ms
vite:rewrite 0ms [no imports] src/batteries/singleton/singleton.ts +81ms
vite:transform 5ms /src/batteries/singleton/singleton.ts +4ms
vite:time 7ms /src/batteries/singleton/singleton.ts +4ms
vite:load 1ms [fs] ../server/src/api/user/route.ts +16ms
vite:load 1ms [fs] /src/batteries/state/state.ts +0ms
vite:resolve 1ms server/src/routes -> /home/some-random-app/packages/server/src/routes.ts
+24ms
vite:transform 4ms ../server/src/api/user/route.ts +15ms
vite:time 6ms ../server/src/api/user/route.ts +15ms
vite:resolve 0ms meiosis-setup/immer -> /home/some-random-app/packages/app/node_modules/.vite/meiosis-setup_immer.js?v=c73c3b06 +1ms
vite:resolve 0ms /node_modules/.vite/meiosis-setup_immer.js?v=c73c3b06 -> /home/some-random-app/packages/app/node_modules/.vite/meiosis-setup_immer.js?v=c73c3b06 +0ms
vite:resolve 0ms meiosis-setup/simple-stream -> /home/some-random-app/packages/app/node_modules/.vite/meiosis-setup_simple-stream.js?v=c73c3b06 +0ms
vite:resolve 0ms /node_modules/.vite/meiosis-setup_simple-stream.js?v=c73c3b06 -> /home/some-random-app/packages/app/node_modules/.vite/meiosis-setup_simple-stream.js?v=c73c3b06 +0ms
vite:resolve 0ms immer -> /home/some-random-app/packages/app/node_modules/.vite/immer.js?v=c73c3b06 +0ms
vite:resolve 0ms /node_modules/.vite/immer.js?v=c73c3b06 -> /home/some-random-app/packages/app/node_modules/.vite/immer.js?v=c73c3b06 +1ms
vite:transform 5ms /src/batteries/state/state.ts +2ms
vite:time 7ms /src/batteries/state/state.ts +2ms
vite:load 0ms [fs] /src/contexts/services/services.ts +32ms
vite:load 0ms [fs] /src/batteries/style/style.ts +2ms
vite:resolve 0ms nanoid/non-secure -> /home/some-random-app/packages/app/node_modules/.vite/nanoid_non-secure.js?v=c73c3b06 +31ms
vite:resolve 0ms /node_modules/.vite/nanoid_non-secure.js?v=c73c3b06 -> /home/some-random-app/packages/app/node_modules/.vite/nanoid_non-secure.js?v=c73c3b06 +0ms
vite:transform 5ms /src/contexts/services/services.ts +31ms
vite:time 6ms /src/contexts/services/services.ts +31ms
vite:resolve 0ms twind/css -> /home/some-random-app/packages/app/node_modules/.vite/twind_css.js?v=c73c3b06 +2ms
vite:resolve 1ms /node_modules/.vite/twind_css.js?v=c73c3b06 -> /home/some-random-app/packages/app/node_modules/.vite/twind_css.js?v=c73c3b06 +1ms
vite:transform 5ms /src/batteries/style/style.ts +3ms
vite:time 7ms /src/batteries/style/style.ts +3ms
vite:load 3ms [fs] npm: daisyui +8ms
vite:load 1ms [fs] ../server/src/routes.ts +8ms
vite:hmr [self-accepts] /home/some-random-app/node_modules/daisyui/dist/full.css +0ms
vite:transform 407ms npm: daisyui +412ms
vite:time 416ms npm: daisyui +414ms
vite:rewrite 1ms [no imports] /home/some-random-app/packages/server/src/routes.ts +466ms
vite:transform 405ms ../server/src/routes.ts +3ms
vite:time 408ms ../server/src/routes.ts +2ms
vite:resolve 0ms /node_modules/.vite/chunk-IHTDASF6.js -> /home/some-random-app/packages/app/node_modules/.vite/chunk-IHTDASF6.js +497ms
vite:time 3ms /node_modules/.vite/chunk-IHTDASF6.js.map +84ms
vite:load 1ms [fs] /src/services/localization/fuzzer.ts +541ms
vite:resolve 0ms pseudo-localization -> /home/some-random-app/packages/app/node_modules/.vite/pseudo-localization.js?v=c73c3b06&es-interop +56ms
vite:resolve 0ms /node_modules/.vite/pseudo-localization.js?v=c73c3b06&es-interop -> /home/some-random-app/packages/app/node_modules/.vite/pseudo-localization.js?v=c73c3b06&es-interop +0ms
vite:resolve 0ms /node_modules/.vite/pseudo-localization.js?v=c73c3b06 -> /home/some-random-app/packages/app/node_modules/.vite/pseudo-localization.js?v=c73c3b06 +1ms
vite:transform 4ms /src/services/localization/fuzzer.ts +140ms
vite:time 5ms /src/services/localization/fuzzer.ts +55ms
vite:time 1ms /src/locales/en/common.json +165ms
vite:hmr [file change] src/main.tsx +22s

THIS IS WHERE I ADD A SINGLE COMMA TO main.tsx AND SAVE - NOW CONTEXT IS FIRING TWICE WITH THE ABOVE PROBLEM

8:52:02 PM [vite] page reload src/main.tsx
vite:spa-fallback Rewriting GET / to /index.html +22s
vite:time 6ms /index.html +21s
vite:cache [304] /@vite/client +0ms
vite:time 1ms /@vite/client +46ms
vite:load 0ms [fs] /src/main.tsx +22s
vite:transform 6ms /src/main.tsx +22s
vite:time 7ms /src/main.tsx +8ms
vite:cache [304] npm: vite +79ms
vite:time 0ms npm: vite +71ms
vite:cache [304] /src/services/api-client/api-client.ts +9ms
vite:time 0ms /src/services/api-client/api-client.ts +9ms
vite:cache [304] /src/services/users/users.ts +1ms
vite:time 0ms /src/services/users/users.ts +1ms
vite:load 1ms [fs] /src/components/organisms/index.ts +88ms
vite:transform 2ms /src/components/organisms/index.ts +84ms
vite:time 5ms /src/components/organisms/index.ts +3ms
vite:cache [304] /src/services/localization/localization.ts +5ms
vite:time 1ms /src/services/localization/localization.ts +3ms
vite:cache [304] /src/contexts/index.ts +2ms
vite:time 1ms /src/contexts/index.ts +1ms
vite:cache [304] /src/batteries/server-client/server-client.ts +14ms
vite:time 1ms /src/batteries/server-client/server-client.ts +14ms
vite:cache [304] /src/batteries/singleton/singleton.ts +16ms
vite:time 1ms /src/batteries/singleton/singleton.ts +16ms
vite:cache [304] /src/config.ts +0ms
vite:time 1ms /src/config.ts +1ms
vite:cache [304] ../server/src/api/user/route.ts +3ms
vite:time 1ms ../server/src/api/user/route.ts +2ms
vite:cache [304] /src/batteries/state/state.ts +17ms
vite:time 1ms /src/batteries/state/state.ts +17ms
vite:load 1ms [fs] /src/components/organisms/app/App.tsx +58ms
vite:transform 3ms /src/components/organisms/app/App.tsx +58ms
vite:time 5ms /src/components/organisms/app/App.tsx +5ms
vite:cache [304] /src/contexts/services/services.ts +28ms
vite:time 1ms /src/contexts/services/services.ts +24ms
vite:cache [304] ../server/src/routes.ts +6ms
vite:time 0ms ../server/src/routes.ts +5ms
vite:cache [304] /src/batteries/style/style.ts +12ms
vite:time 0ms /src/batteries/style/style.ts +12ms
vite:cache [memory] /src/main.tsx +0ms
vite:time 0ms /src/main.tsx +1ms
vite:cache [304] npm: daisyui +6ms
vite:time 1ms npm: daisyui +5ms
vite:time 2ms /node_modules/.vite/chunk-IHTDASF6.js.map +126ms
vite:cache [304] /src/services/localization/fuzzer.ts +213ms
vite:time 0ms /src/services/localization/fuzzer.ts +87ms
vite:time 0ms /src/locales/en/common.json +62ms

I've added a comment about halfway through the trace where I save a file and Vite recompiles causing the problems described above.

Stacktraces of the 2 context calls done in the component console.log(useContext(...))
App | @ | App.tsx:28
-- | -- | --
  | renderWithHooks | @ | react-dom.development.js:14985
  | mountIndeterminateComponent | @ | react-dom.development.js:17811
  | beginWork | @ | react-dom.development.js:19049
  | beginWork$1 | @ | react-dom.development.js:23940
  | performUnitOfWork | @ | react-dom.development.js:22779
  | workLoopSync | @ | react-dom.development.js:22707
  | renderRootSync | @ | react-dom.development.js:22670
  | performSyncWorkOnRoot | @ | react-dom.development.js:22293
  | scheduleUpdateOnFiber | @ | react-dom.development.js:21881                               <-- Different
  | updateContainer | @ | react-dom.development.js:25482
  | (anonymous) | @ | react-dom.development.js:26021
  | unbatchedUpdates | @ | react-dom.development.js:22431
  | legacyRenderSubtreeIntoContainer | @ | react-dom.development.js:26020              <-- Until here
  | render | @ | react-dom.development.js:26103
  | main | @ | main.tsx:30
  | async function (async) |   |  
  | main | @ | main.tsx:20
  | (anonymous) | @ | main.tsx:40
------------------------------------------
  | App | @ | App.tsx:28
-- | -- | -- | --
  | renderWithHooks | @ | react-dom.development.js:14985
  | mountIndeterminateComponent | @ | react-dom.development.js:17811
  | beginWork | @ | react-dom.development.js:19049
  | beginWork$1 | @ | react-dom.development.js:23940
  | performUnitOfWork | @ | react-dom.development.js:22779
  | workLoopSync | @ | react-dom.development.js:22707
  | renderRootSync | @ | react-dom.development.js:22670
  | performSyncWorkOnRoot | @ | react-dom.development.js:22293
  | (anonymous) | @ | react-dom.development.js:11327                                     <-- Different
  | unstable_runWithPriority | @ | scheduler.development.js:468
  | runWithPriority$1 | @ | react-dom.development.js:11276
  | flushSyncCallbackQueueImpl | @ | react-dom.development.js:11322
  | flushSyncCallbackQueue | @ | react-dom.development.js:11309
  | scheduleUpdateOnFiber | @ | react-dom.development.js:21893
  | updateContainer | @ | react-dom.development.js:25482
  | legacyRenderSubtreeIntoContainer | @ | react-dom.development.js:26037              <-- Until here
  | render | @ | react-dom.development.js:26103
  | main | @ | main.tsx:30
  | async function (async) |   |  
  | main | @ | main.tsx:20
  | (anonymous) | @ | main.tsx:40

There's nothing in the component to make it render twice (and when Vite restarts before HMR is done it does render only once). Yet here 2 calls are made that differ in how they were triggered

I've traced down the problem to defining the context in the same file where I called ReactDOM.render. Since I defined the context here I also export it (to be able to consume it in other components). Since this is the place I call the final render though it's also the place I import those components which creates a cyclic dependency.

The problem then is either the cyclicity and HMR breaking it. Or HMR doing something to the compiled code which creates the context twice which then causes a whole bunch of errors and weird behaviour.

Either way, don't define context's in the same file as you call ReactDOM.render kids #TIL

@piyushere
Copy link

piyushere commented Dec 9, 2021

I am also facing the same issue and indeed it's related to Vite or @vitejs/plugin-react. I have tried to run the same application using the react-scripts package (used by create-react-app) and I was able to preserve the state even after modifying the context provider.

Wondering if it's because Vite HMR triggers component reload (resetting any previous state) on modifying initial state values:

// CounterContext.jsx
const CounterContext = createContext({
  counter: 0,
  setCounter: (value) => { console.log('this is default value') }
})
/* CouterProvider ... */


// MyComponent.jsx
const MyComponent = (props) => {
  const { counter, setCounter } = useContext(CounterContext);
  /* Render logic ... */
}

When CounterContext.jsx is modified, the counter and setCounter inside MyComponent.jsx are assigned the default context values and you can see it printing "this is default value" on calling setCounter.

@iamhmx
Copy link

iamhmx commented Feb 21, 2022

@selrond Is there a solution to this problem?

@nthurnau
Copy link

While attempting to migrate an app that uses context quite a bit, this has blocked me from moving forward as well. It would be great to get an update on whether or not this is going to be worked on. It seems to happen when the createContext hook is in the same file as the component where the Provider is used. In my case, I don't have a clean way to insert it on a parent component without wrapping my entire app where the routes are, which is not something I wish to do. I found a related issue in Snowpack, which also uses esbuild to do HMR.

@arifszn

This comment was marked as spam.

@tekclawltd

This comment was marked as spam.

@pablocdev
Copy link

pablocdev commented Mar 27, 2022

Same issue here, but im trying to be more specific with that.

In my experience:

  1. IN THE SAME FILE. Creates a context, and exports a provider
export const Context = createContext();

export const Provider = ({children}) => (
  <Context.Provider value={/* whatever*/}>{children}</Context.Provider>
)

Running npm run dev works.
Forcing a hot reload on this file, crashes (context gets default value for all useContext calls).

  1. IN SEPARATED FILES
export const Context = createContext();
import { Context } from './my-context-file';

export const Provider = ({children}) => (
  <Context.Provider value={/* whatever*/}>{children}</Context.Provider>
)

Running npm run dev works.
Forcing a hot reload on any of those files, still works.

Tell me if you need more info, or a minium reproduction repo.

Hope it helps!

@stregouet
Copy link

I'm also stuck with issue related to Context and HMR/fast refresh.
In my case createContext and Provider are in separated files. If I modify a component with useContext, HMR reloads my component but I get an error which means that useContext return default value (the value in createContext: export const MyContext = createContext({ a: "foo"})) but I need value from Provider (<MyContext.Provider value={b: "bar"}>)

To workaround this issue, I just use { fastRefresh: false } option in @vitejs/plugin-react which is clearly disappointing when you are used { fastRefresh: true } ;)

@haoqunjiang haoqunjiang added p3-minor-bug An edge case that only affects very specific usage (priority) and removed pending triage labels Apr 20, 2022
@adnanalbeda
Copy link

adnanalbeda commented May 23, 2022

In my case, I was trying to add a MobX store with default provider:

export class Store implements StoreSchema {
  commonStore = new CommonStore();
  userStore = new UserStore();
}

export const store = new Store();

export const StoreContext = createContext(store);

export const useStore = () => {
  return useContext(StoreContext);
};

then calling it in the main.tsx:

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <StoreContext.Provider value={store}> {/* */}
      <CustomRouter history={history}>
        <App />
      </CustomRouter>
    </StoreContext.Provider>
  </React.StrictMode>
);

It works at first, but after any change, (whether in context, component, style, etc.), and hot reload, I get a white screen with this error in console:

Uncaught ReferenceError: can't access lexical declaration 'StoreContext' before initialization

Update - Creating context and provider in one file partially solves the problem.

However, still editing inside the context itself break the code and require page refresh.

Here is what I tried:

interface StoreSchema {
  commonStore: CommonStore;
  userStore: UserStore;
}

export class Store implements StoreSchema {
  commonStore = new CommonStore();
  userStore = new UserStore();
}

export const store = new Store();

const storeContext = createContext(store);

export const StoreContextProvider = (props: { children: ReactNode | JSX.Element }) => {
  return <storeContext.Provider value={store}>{props.children}</storeContext.Provider>;
};

export const useStore = () => {
  return useContext(storeContext);
};

and only call the StoreContextProvider in main.tsx:

let reactRoot;

// to avoid react console warning: root is already defined.
if (!reactRoot) {
  const root = document.getElementById("root");
  if (root) { // to avoid eslint warning on using non-null assertion
    reactRoot = ReactDOM.createRoot(root);
  } else {
    console.error("No root element is defined in the index file.");
  }
}

reactRoot?.render(
  <React.StrictMode>
    <StoreContextProvider>
      <CustomRouter history={history}>
        <App />
      </CustomRouter>
    </StoreContextProvider>
  </React.StrictMode>
);

@iceniveth
Copy link

Same issue here, but im trying to be more specific with that.

In my experience:

  1. IN THE SAME FILE. Creates a context, and exports a provider
export const Context = createContext();

export const Provider = ({children}) => (
  <Context.Provider value={/* whatever*/}>{children}</Context.Provider>
)

Running npm run dev works. Forcing a hot reload on this file, crashes (context gets default value for all useContext calls).

  1. IN SEPARATED FILES
export const Context = createContext();
import { Context } from './my-context-file';

export const Provider = ({children}) => (
  <Context.Provider value={/* whatever*/}>{children}</Context.Provider>
)

Running npm run dev works. Forcing a hot reload on any of those files, still works.

Tell me if you need more info, or a minium reproduction repo.

Hope it helps!

I tried the 2nd option, though it does work with HMR. We kind-a lose the capability of Fast Refresh. While fast refresh is still buggy, I think disabling it for now is the only workaround ☹️: #3301 (comment)

@stregouet
Copy link

I finally find a trick to make it works => implement my own vite plugin which automatically wraps createContext call with a lookup in local cache
I found this trick in jotai repo

@kalda341
Copy link

@stregouet This sounds really promising - would you be able to share your plugin? I have a repo that has turned into a bit of a nightmare to work on because of this issue.

@stregouet
Copy link

@kalda341 I didn't publish it anywhere because it is not really robust and a bit too specific to my case.

anyway here is the code:

import type { Plugin, ResolvedConfig } from "vite";

export default function cacheContext() {
    let config: ResolvedConfig;
    const p: Plugin = {
        name: "myorg:cache-context",
        configResolved(resolvedConfig) {
            // store the resolved config
            config = resolvedConfig;
        },
        transform(src, id) {
            if (config.command !== "serve") {
                // not in dev mode
                return;
            }
           // this if allow me to speed up plugin process, since all of my context 
           // are located in `context` directory
            if (!/mypkg\/src\/context/.test(id)) {
                return;
            }
            return {
                code:
                    `
window.contextCache = window.contextCache || {
  cache: new Map(),
  get(key, inst) {
    if (this.cache.has(key)) {
      return this.cache.get(key);
    }
    this.cache.set(key, inst);
    return inst;
  }
};
` +
                    src.replace(
                        /export const ([^=]*)=\s*React.createContext\(([^;]*);/g,
                        (_, name: string, value: string) =>
                            `export const ${name} = ` +
                            `window.contextCache.get("${name.trim()}", React.createContext(${value});`,
                    ),
                map: null,
            };
        },
    };
    return p;
}

you see, it is regex based, but to manipulate code it is better and more robust to use something like babel (as jotai did)

@liho00
Copy link

liho00 commented Jul 1, 2022

same issue here, export useContext will be break when hot reload... feeling weird, and im still trying figure out the solution...

I'm also stuck with issue related to Context and HMR/fast refresh. In my case createContext and Provider are in separated files. If I modify a component with useContext, HMR reloads my component but I get an error which means that useContext return default value (the value in createContext: export const MyContext = createContext({ a: "foo"})) but I need value from Provider (<MyContext.Provider value={b: "bar"}>)

To workaround this issue, I just use { fastRefresh: false } option in @vitejs/plugin-react which is clearly disappointing when you are used { fastRefresh: true } ;)

i tried this, wont work... I still had to manually refresh everytime when i save work on my vite project tho.

Could anyone tell me which old version did not have this problem, i wish to downgrade temporary to continue work with my project smoothly...

image

I saw this everytime i save the code (Tony's bug)

@sodatea can we mark it as major bug?

I found an temporary solution which is downgrade the vite version to v2.5.0 and use @vitejs/plugin-react-refresh instead of @vitejs/plugin-react should works without the Tony's bug.

image

@wenerme
Copy link

wenerme commented Jul 13, 2022

Vite 3 is out, but React context still do not support HMR

@liho98
Copy link

liho98 commented Jul 13, 2022

Vite 3 is out, but React context still do not support HMR

Some correction, Vite 3 is out, however Vite 3's HMR still didn't support React Context yet.

Your welcome!

Hence I would not recommend react developers using vite as development tool. Hence, u see Nextjs, ionic, and bunch of huge react frameworks still did not using vite yet. Nextjs, Webpack are much more mature for react development, however vite is more focus on vue 3 based on my understanding 👍

Some add on, React Context is great feature, without React context, We cant build a scalable and huge react project with ease!

For those thumb down reaction, please share your thought and tell me am i say something wrong? Please correct me if im wrong, Thanks!

@seeker-3
Copy link

I have this same issue. Whenever I modify the context, I usually have to a manual page reload to fix it.

I thought it'd be cool if vite had a feature where I could add a comment to the top of a file like
// @vite full-page-reload

I could put at the top of a react context file to do page reload instead of HMR when I edit that file.

@AndrewLeedham
Copy link

I have this same issue. Whenever I modify the context, I usually have to a manual page reload to fix it.

I thought it'd be cool if vite had a feature where I could add a comment to the top of a file like
// @Vite full-page-reload

I could put at the top of a react context file to do page reload instead of HMR when I edit that file.

@seeker-3 I believe you could use the HMR API to achieve the same: https://vitejs.dev/guide/api-hmr.html#hot-decline

@iceniveth
Copy link

iceniveth commented Jul 19, 2022

Hence I would not recommend react developers using vite as development tool. Hence, u see Nextjs, ionic, and bunch of huge react frameworks still did not using vite yet.

We have been using CRA with typescript from version 2.X to 4.X. In the span of three years our codebase grew a lot. Starting our application locally takes more than a minute. Building it is even slower in CI, more than 15 minutes. Hot reloading also took more than five seconds.

Migrating to Nextjs would require a lot of refactorings on our end since we heavily rely on React context as global state management. And it's routing is based on file system which makes it complicated to migrate our app.

After migrating CRA to Vite we've managed to speed up starting our application from more than a minute to instantaneous (less than a second). And the build took less than 9 minutes (more than 15 minutes before). Hot reloading Live reload is also fast.

@liho98
Copy link

liho98 commented Jul 19, 2022

Hence I would not recommend react developers using vite as development tool. Hence, u see Nextjs, ionic, and bunch of huge react frameworks still did not using vite yet.

We have been using CRA with typescript from version 3.X to 4.X. In the span of three years our codebase grew a lot. Starting our application locally takes more than a minute. Building it is even slower in CI, more than 15 minutes. Hot reloading also took more than five seconds.

Migrating to Nextjs would require a lot of refactorings on our end since we heavily rely on React context as global state management. And it's routing is based on file system which makes it complicated to migrate our app.

After migrating CRA to Vite we've managed to speed up starting our application from more than a minute to instantaneous (less than a second). And the build took less than 9 minutes (more than 15 minutes before). Hot reloading is also fast.

weird tho, vite does not support react context when hot reloading, how could you development your app, manually refreshing the page/app every time after hot reload? dont you feel troublesome when developing react app with this behavior?

@iceniveth
Copy link

iceniveth commented Jul 19, 2022

how could you development your app, manually refreshing the page/app every time after hot reload

Ours automatically reloads whenever a file has been saved.

There are a lot of guides roaming around. Like this one: https://www.darraghoriordan.com/2021/05/16/migrating-from-create-react-app-to-vite/

Though we have a lot of dependencies issues but we managed to resolve them all.

@SeanRoberts
Copy link

@adnanalbeda Yes correct, SomethingA gets what is provided at the first level and SomethingB gets provided at the second level. If we use the preserveRef plugin, then both providers would have the same key, because in my example the key would be "MyContext". Thus, they would both be in contention when writing to import.meta.hot.data.contexts["MyContext"].

Again, nesting providers of the same context is not a popular thing to do, but I'm just pointing out the limitation to keying the context data.

This is the kind of edge case behaviour that would probably affect very few people but those affected would likely be driven to the brink of insanity before they figured out what was causing it 😅

@justinbhopper
Copy link

This is the kind of edge case behaviour that would probably affect very few people but those affected would likely be driven to the brink of insanity before they figured out what was causing it 😅

Agreed. 🙂 I think most here would love this plugin once its written, because it's basically plug-and-play and handles 99% of use cases.

@adnanalbeda
Copy link

adnanalbeda commented Jul 21, 2022

@justinbhopper It works so smooth with no issues.
HMR don't break the provider anymore.

Here's the steps:

1- create a new vite react ts project.
2- inside App.tsx, add this code:

import { Children, createContext, useContext, useState } from 'react'
import logo from './logo.svg'
import './App.css'

const Context = createContext({ hello: "default context" });

function LoadContextData(props: { children?: React.ReactNode }) {
  const context = useContext(Context);
  return <>
    <div>
      {context.hello}
      {props.children}
    </div>
  </>
}

function App() {
  const [count, setCount] = useState(0)
  const context = useContext(Context); // No providers - should show the default value
  return (
    <div className="App">
      {context.hello}
      <Context.Provider value={{ hello: "first level provider" }}>
        <LoadContextData>
          <Context.Provider value={{ hello: "second level provider" }}>
            <LoadContextData>
              <div>
                Edit Here, it works perfectly well.
              </div>
            </LoadContextData>
          </Context.Provider>
        </LoadContextData>
      </Context.Provider>
    </div>
  )
}

export default App

3- Inside vite.config.ts, add this plugin:

const reactContextHmr = () => {
  const preverseRefFunc = `
  function __preserveRef(key, v) {
    if (import.meta.env.PROD) return v;
    
  import.meta.hot.data ??= {}
  import.meta.hot.data.contexts ??= {}
  const old = import.meta.hot.data.contexts[key];
  const now = old || v;
  
  import.meta.hot.on('vite:beforeUpdate', () => {
    import.meta.hot.data.contexts[key] = now;
  });
  
  return now;
}
`;
  const createContextRegEx = /(import.*createContext.*react)|(React.createContext.*\(.*\))/;
  const oldCreateRegex = /(const|let) (.*) = ((React\.createContext.*)|(createContext.*));/;
  const newCreateRegex = "$1 $2 = __preserveRef(\"$2\",$3);";

  return {
    name: 'preserveRef',
    transform(code: string) {
      if (!code.match(createContextRegEx)) return;

      return {
        code: (code + preverseRefFunc).replace(oldCreateRegex, newCreateRegex),
        map: null,
      };
    },
  };
};

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react(), reactContextHmr()]
})

And it works.

Now we just need some better regex matching rules.


Update 1:

Tried this with context in a separated file, it doesn't work.

@sapphi-red
Copy link
Member

@adnanalbeda

If this works, then I think it's possible to do a more complete implementation for it, so it can be more generic and less needing for calling __preserveRef.

Yes, it's possble. For now, I wanted to avoid caveats while using the plugin. The best way is to write a babel transform, but it requires some work and I wanted to check if this works for people.

Tried this with context in a separated file, it doesn't work.

Do you have a reproduction of this one?


@justinbhopper

I should also point out that this preserveRef solution does not handle nesting of the same context within itself.

I didn't think of that, but it seems it's working well? (stackblitz)

@adnanalbeda
Copy link

@sapphi-red your method works perfectly well, with nested level, separated files and everything.
I tried editing in CounterPovider, Counter, and App.
All are good, and works with the expected normal behavior.

@brunopuzoni
Copy link

To workaround, add this plugin:

Worked like a charm for our usecase on a medium-large project.
Thank you @sapphi-red

@adnanalbeda
Copy link

Can someone confirm this?

I just ran vite@2.9.9 with vitejs/plugin-react@1.3.0, got the whole code from this chad @sapphi-red , but without the plugin. and the __preserveRef.

Then tried to edit the context, counter, app, etc. and all worked with no issues.

@justinbhopper
Copy link

@adnanalbeda I also cannot reproduce the bug using the original repo (https://github.com/selrond/vite-react-usecontext) after upgrading it to vite@3.0.2 and @vitejs/plugin-react@2.0.0. Is this bug still occurring in latest?

https://stackblitz.com/edit/github-6861mq-hcsekc

@adnanalbeda
Copy link

Great, so the issue is resolved, and no one knows why.

@sapphi-red
Copy link
Member

sapphi-red commented Jul 22, 2022

It still happens for me.
Open src/CountProvider.jsx and edit that file (not other files).
https://stackblitz.com/edit/github-6861mq-6f4ezn?file=src%2FCountProvider.jsx

@adnanalbeda
Copy link

@sapphi-red , are you trying it locally? or just on stackblitz?

@sapphi-red
Copy link
Member

I was trying on stackblitz. But I tried it now with local and it happened.

@adnanalbeda
Copy link

adnanalbeda commented Jul 22, 2022

Thanks, now I know what's going on.

DON'T define the context with its provider in the SAME FILE.

HMR will break if any change happen in that file, or any file that is used in the context or the provider.

More about it.

If we have one file with this code:

import React from 'react';

export const CountContext =
    // __preserveRef("CountContext", React.createContext<any>(null));
    React.createContext<any>(null)
    ;

export const CountContextProvider = (props: { children: React.ReactNode }) => {
    const [count, setCount] = React.useState(1);
    return (<CountContext.Provider value={{ count, setCount }}>
        {props.children}
    </CountContext.Provider>)
}

Any change here, HMR will break.

But separate them into two files:

// CountContext(.ts or .tsx)
import React from 'react';

export const CountContext =
    // __preserveRef("CountContext", React.createContext<any>(null));
    React.createContext<any>(null)
    ;

and

// CountContext.tsx
import React from "react";
import { CountContext } from "./CountContext";

export const CountContextProvider = (props: { children: React.ReactNode }) => {
    const [count, setCount] = React.useState(1);
    return (<CountContext.Provider value={{ count, setCount }}>
        {props.children}
    </CountContext.Provider>)
}

In this way, the issue is resolved, and changes can happen safely everywhere.


I will test it next with a simple mobx store and see what happens.


Update:

After adding a small mobx store, I can confirm, this issue only happens when both context and provider are defined in the same file.
Now we need to know, why?

@Geloosa
Copy link

Geloosa commented Jul 26, 2022

The same issue with provide/inject in Vue.
When editing any component in the tree that shares the state provided in the root, provided state and key are lost after the hot reload, emitting an error injection "Symbol(auth-state)" not found.
Reproducing both in Vite 2 and Vite 3.

@andrewluetgers
Copy link

Just ran into this issue on a non-vite project. We are introducing context for the first time into our app. After messing around I finally found that yes moving the createContext call to another file resolves the issue mostly. Editing that file still causes the problem.

@danielrentz
Copy link

danielrentz commented Aug 23, 2022

FYI, we stumbled over this problem too, and are using a (somewhat hacky) solution that seems to work, without needing to write Vite plugins or fiddling with HMR API.

The trick is to move the "createContext" call into the provider component. Using a React ref ensures uniqueness.

What do you think? Does this solution have any downsides I am not aware of (except that this has to be repeated for every context, and goes into production code)?

import { createContext, useContext, useRef } from "react";

let MyContext;

export function MyProvider({ children }) {
    const ref = useRef();
    MyContext = ref.current ??= createContext();
    ...
    return <MyContext.Provider value={...}>{children}</MyContext.Provider>;
}

export default function useMyContext() {
    return useContext(MyContext);
}

@IanVS
Copy link
Contributor

IanVS commented Aug 31, 2022

This might be related to vite performing HMR too eagerly: #9869.

@astoilkov
Copy link

astoilkov commented Sep 12, 2022

I noticed the 54 likes, the 47 comments, a few duplicate issues, and the implementation of fastRefresh property in the configuration, so the issue can have a workaround.

The issue doesn't feel it deserves the p3-minor-bug 🔨 label.

@wenerme
Copy link

wenerme commented Sep 12, 2022

It's still a strong reason to choose nextjs instead of vitejs just because of context losing, in real app, a context losing will easily cause a tab 100% CPU because of an error loop, have to keep a task manager open and kill the tab.

@kalda341
Copy link

Not sure why people are thumbs downing @wenerme - I'm working on a very large app where these HMR issues are leading to all kinds of unpredictable issues. In some cases this does lead to having to kill the tab, in some cases it leads to unexpected app behaviors, and in some cases an Auth0 redirect loop (which is so hard to debug that I'm not even 100% sure it's related to this issue). It really is a massive headache for me and my team, though the size of the app means that disabling fastRefresh is also not a great solution.

@IanVS
Copy link
Contributor

IanVS commented Sep 26, 2022

I've pushed up a PR that fixes this issue, according to a test I wrote based off the reproduction in the issue description. But, it requires a change to how Vite handles import.meta.hot.invalidate(), so I think it will need some discussion with the Vite team.

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
Development

Successfully merging a pull request may close this issue.