Skip to content

Issue with named exports and filenames #1

@EmilNordling

Description

@EmilNordling

Hi!

Been lurking over the progress of this package for a while now and you've done amazing work to implement fast refresh for TypeScript, a true game changer! I haven't found time to a try it out until recently and these where the issues I ran into:

  • If a module is exporting its React component as named instead of default, it'll throw error.
  • If a module is not named exactly as its default exported React component, it'll not recover state.

In a Babel setup, it is working to have both named export and non-matching filenames to the component.

If I weren't too unfamiliar with custom ts transformers, I'd try to create a PR! But I don't have that experience unfortunately, what I can do is provide a branch where these errors occurd in: https://github.com/one-atom/one-atom/tree/react-fast-refersh-typescript

To Reproduce

Named export steps

  1. Checkout said remote branch
  2. Once node modules are installed, run the npm script build at root.
  3. Go into $ cd modules/bundler/test/fixtures/run_dev_typescript
  4. Run $ node run.dev.js
  5. In port 8000, the error TestComponent is not defined is thrown

What we can do now it is to replace the named export to a default one. It'll stop throwing error but now if a change is made in react_fast_refresh_check.tsx it'll not recover state.

Filename recovering state steps

  1. "fix" the Named export steps
  2. Increment the counter
  3. Make an update in react_fast_refresh_check.tsx
  4. Counter is now reseted to 0.

Only when react_fast_refresh_check.tsx is renamed to TestComponent.tsx it'll not behave like this and actually recover the state.

Expected behavior

Should not need to do the changes above, it should work as the correspondent Babel setup.

Babel setup can be found here:
modules/bundler/test/fixtures/run_dev_typescript

It also as got an equivalent run.dev.js script


With that said, I would like to ask a question about ts transformers that's related to react-refresh but probably not for this package to handle.

At the company I work for we've been using React with TypeScript for a long time, way before official support was added, and up to this day we've been using a quite unconventional way to structure our components. They basically look like this:

// In a file components/example.component.ts
export namespace Example {
  export interface Props {
    title: string;
  }

  export const h: FC<Props> = function Example({ title }) {
    return <div>{title}</div>;
  }
}

// main.tsx
ReactDOM.render(<Example.h title="Hello World!" />, document.getElementById('root'));

while it's one of a kind, it solved issues we had getting TypeScript to fit into a large codebase without having types and lesser components bloating everything.

So my question is; do you know, with your knowledge, if it would be feasible to apply some transformation to get our unconventional components to utilize react-refresh as well?

From my understanding, react-refresh is quite picky to what it thinks is a React component. I figure since our components are always named .component., maybe a custom transformation can be done for these files to turn them into something react-refresh conciders as a recognizable component?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions