Skip to content

Conversation

@Newbie012
Copy link
Contributor

closes #493

Copy link
Member

@ArnaudBarre ArnaudBarre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this and adding the test!
I don't think we need to logic twice, I think this can be done like this:

if (isLikelyComponentType(exportValue)) {
  register(...)
} else if (/* is obj & all keys are component */ ) {
      for (const subKey in exportValue) {
        register(
          exportValue[subKey],
          filename + ' export ' + key + '$' + subKey,
        )
      }
}

@Newbie012
Copy link
Contributor Author

I'll check and keep you posted

@ArnaudBarre
Copy link
Member

My bad the code in isLikelyComponent is needed for the "validateRefreshBoundaryAndEnqueueUpdate" function.

@Newbie012
Copy link
Contributor Author

Newbie012 commented Jul 1, 2025

You're fast! I was just about to comment that I don't think the tests are passing 😅 I reverted back to the original changes.

@Newbie012
Copy link
Contributor Author

Is there something that I can help with in order to merge this change?

@ArnaudBarre ArnaudBarre requested a review from sapphi-red July 15, 2025 23:37
@ArnaudBarre
Copy link
Member

ArnaudBarre commented Jul 15, 2025

@Newbie012 I was not very satisfied with the recursive nature of the current code. It would have return true for deeply nested object with only React component, but the runtime parts did not do it recursively. I think one level is enough.
Separating in two functions also avoid registering the top level object of compound components as react component (I think it's a no op but it's cleaner).
I also changed the code to bail out as fast as possible when testing for "compound components"

@ArnaudBarre ArnaudBarre requested a review from sapphi-red July 16, 2025 08:52
@hi-ogawa hi-ogawa merged commit fdc9d9a into vitejs:main Jul 18, 2025
9 checks passed
@GuskiS
Copy link

GuskiS commented Jul 20, 2025

Can this be extended to support this syntax?

export function Accordion() {
  return <div></div>;
}

Accordion.Root = () => <div>Accordion Root</div>
Accordion.Item = () => <div>Accordion Item</div>

renovate bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Aug 4, 2025
| datasource | package              | from  | to    |
| ---------- | -------------------- | ----- | ----- |
| npm        | @vitejs/plugin-react | 4.6.0 | 4.7.0 |


## [v4.7.0](https://github.com/vitejs/vite-plugin-react/blob/HEAD/packages/plugin-react/CHANGELOG.md#470-2025-07-18)

##### Add HMR support for compound components ([#518](vitejs/vite-plugin-react#518))

HMR now works for compound components like this:

```tsx
const Root = () => <div>Accordion Root</div>
const Item = () => <div>Accordion Item</div>

export const Accordion = { Root, Item }
```

##### Return `Plugin[]` instead of `PluginOption[]` ([#537](vitejs/vite-plugin-react#537))

The return type has changed from `react(): PluginOption[]` to more specialized type `react(): Plugin[]`. This allows for type-safe manipulation of plugins, for example:

```tsx
// previously this causes type errors
react({ babel: { plugins: ['babel-plugin-react-compiler'] } })
  .map(p => ({ ...p, applyToEnvironment: e => e.name === 'client' }))
```
renovate bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Aug 5, 2025
| datasource | package              | from  | to    |
| ---------- | -------------------- | ----- | ----- |
| npm        | @vitejs/plugin-react | 4.6.0 | 4.7.0 |


## [v4.7.0](https://github.com/vitejs/vite-plugin-react/blob/HEAD/packages/plugin-react/CHANGELOG.md#470-2025-07-18)

##### Add HMR support for compound components ([#518](vitejs/vite-plugin-react#518))

HMR now works for compound components like this:

```tsx
const Root = () => <div>Accordion Root</div>
const Item = () => <div>Accordion Item</div>

export const Accordion = { Root, Item }
```

##### Return `Plugin[]` instead of `PluginOption[]` ([#537](vitejs/vite-plugin-react#537))

The return type has changed from `react(): PluginOption[]` to more specialized type `react(): Plugin[]`. This allows for type-safe manipulation of plugins, for example:

```tsx
// previously this causes type errors
react({ babel: { plugins: ['babel-plugin-react-compiler'] } })
  .map(p => ({ ...p, applyToEnvironment: e => e.name === 'client' }))
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add HMR Support for Compound Component Pattern

5 participants