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

Fast Refresh not working with hooks returning JSX/TSX #354

Open
7 tasks done
mpressmar opened this issue Aug 7, 2024 · 5 comments
Open
7 tasks done

Fast Refresh not working with hooks returning JSX/TSX #354

mpressmar opened this issue Aug 7, 2024 · 5 comments
Labels
bug Something isn't working

Comments

@mpressmar
Copy link

Describe the bug

We are frequently using custom hooks that will return rendering callbacks in which we refer to actual tsx components.

Is this a bug, or is there any alternative for defining component-based hooks which doesn't break HMR?

Reproduction

https://stackblitz.com/edit/vitejs-vite-zzqhfn?file=src%2Fhook.jsx

Steps to reproduce

A simple example:

hook.tsx

import { useCallback } from "react";

export const useExampleHook = () => {
    return useCallback(() => <span>Test</span>, []);
}

If you use this hook in a component, and then modify the hook's source code, the following will be printed in the console:

5:03:45 PM [vite] hmr invalidate /src/hook.tsx Could not Fast Refresh. Learn more at https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react#consistent-components-exports

System Info

Linux Mint, Firefox, Vite 5.2.11, latest vite react plugin

Used Package Manager

npm

Logs

No response

Validations

@ArnaudBarre ArnaudBarre added bug Something isn't working and removed pending triage labels Aug 7, 2024
@ArnaudBarre
Copy link
Member

This is a duplicate of #289, but thanks for the small repro I'll look into it I didn't though it was that easy to trigger

@dbarabashh
Copy link

if i'm not mistaken, plan uses the regular expression defaultIncludeRE = /\.[tj]sx?$/ to identify the files that need to be processed. i think it makes more sense to check for the presence of jsx syntax in the code and implement something like this

if (tsRE.test(id) && !id.endsWith('.tsx')) {
      const hasJsx = jsxContentRE.test(code)
      if (hasJsx) {
        this.warn(
          `File ${id} contains JSX but has a .ts extension. ` +
            `Consider renaming to .tsx or adding "// @jsx" pragma comment.`,
        )
      }
}

now, when using hooks with jsx in .ts files, you'll get a warning that will guide you to properly configure your project. if i understood correctly, this should solve the problem somehow. but i'm not entirely sure how to properly test it considering what we have in the playground. overall, if this is what's needed, i could try to implement it

cc @ArnaudBarre

@ArnaudBarre
Copy link
Member

The issue is about having correct JSX configure or about file extensions. The code in the issue should correctly get handled but it's not due to how fast refresh works (I think it's possible to do fast refresh for hooks only, but I never correctly implemented it, and it creates this annoying warning).

@dbarabashh
Copy link

then here we need to add a check for the presence of jsx or createElement() as well, right?

const isJSX = filepath.endsWith('x')

its just that this check doesnt cover all the cases i think

@ArnaudBarre
Copy link
Member

The issue is not detecting is the file is JSX, the issue is correctly detecting if the file should be HMRed.
Removing Sig from const refreshContentRE = /\$Refresh(?:Reg|Sig)\$\(/ should fix the warning, but I want to investigate how fast refresh for hooks only works. to this is this can be lead to cleaner HMR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants