Skip to content

Support module.property.useHook() in Fast Refresh#35318

Open
ArnaudBarre wants to merge 1 commit into
react:mainfrom
ArnaudBarre:refresh-nested-hooks-call
Open

Support module.property.useHook() in Fast Refresh#35318
ArnaudBarre wants to merge 1 commit into
react:mainfrom
ArnaudBarre:refresh-nested-hooks-call

Conversation

@ArnaudBarre

@ArnaudBarre ArnaudBarre commented Dec 7, 2025

Copy link
Copy Markdown
Contributor

Summary

Fixes vitejs/vite-plugin-react#1006

I'm not sure a lot of users do nest hooks at the second level, but the added complexity to the Babel plugin fells low enough to add support to it.

Before this change, the signature for the test would have been _s(App, "useNestedThing{foo}", true) which would force reset on HMR.

@meta-cla meta-cla Bot added the CLA Signed label Dec 7, 2025
@react-sizebot

Copy link
Copy Markdown

Comparing: 4174533...217828a

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.js = 6.84 kB 6.84 kB = 1.88 kB 1.88 kB
oss-stable/react-dom/cjs/react-dom-client.production.js = 608.36 kB 608.36 kB = 107.68 kB 107.68 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 6.84 kB 6.84 kB = 1.88 kB 1.88 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js = 667.47 kB 667.47 kB = 117.57 kB 117.57 kB
facebook-www/ReactDOM-prod.classic.js = 693.67 kB 693.67 kB = 122.07 kB 122.07 kB
facebook-www/ReactDOM-prod.modern.js = 684.10 kB 684.10 kB = 120.45 kB 120.45 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
oss-experimental/react-refresh/cjs/react-refresh-babel.production.js +0.81% 20.63 kB 20.80 kB +0.42% 4.08 kB 4.09 kB
oss-stable-semver/react-refresh/cjs/react-refresh-babel.production.js +0.81% 20.63 kB 20.80 kB +0.42% 4.08 kB 4.09 kB
oss-stable/react-refresh/cjs/react-refresh-babel.production.js +0.81% 20.63 kB 20.80 kB +0.42% 4.08 kB 4.09 kB
oss-experimental/react-refresh/cjs/react-refresh-babel.development.js +0.79% 22.10 kB 22.27 kB +0.43% 4.15 kB 4.17 kB
oss-stable-semver/react-refresh/cjs/react-refresh-babel.development.js +0.79% 22.10 kB 22.27 kB +0.43% 4.15 kB 4.17 kB
oss-stable/react-refresh/cjs/react-refresh-babel.development.js +0.79% 22.10 kB 22.27 kB +0.43% 4.15 kB 4.17 kB

Generated by 🚫 dangerJS against 217828a

@Dunqing

Dunqing commented Dec 7, 2025

Copy link
Copy Markdown

The issue you linked in the description is incorrect. Should be vitejs/vite-plugin-react#1006, right?

@ArnaudBarre

Copy link
Copy Markdown
Contributor Author

yeah my bad!

Copilot AI added a commit to oxc-project/oxc that referenced this pull request Dec 8, 2025
…fresh

Add support for detecting hooks called via nested member expressions like
`FancyHook.property.useNestedThing()` in React Fast Refresh.

Previously, only direct hook calls and single-level member expressions were
supported. This caused nested member expression hooks to force a full reset
on HMR instead of preserving state.

This implementation matches React PR #35318:
react/react#35318

Co-authored-by: Dunqing <29533304+Dunqing@users.noreply.github.com>
@github-actions

github-actions Bot commented Mar 7, 2026

Copy link
Copy Markdown

This pull request has been automatically marked as stale. If this pull request is still relevant, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize reviewing it yet. Your contribution is very much appreciated.

@github-actions github-actions Bot added the Resolution: Stale Automatically closed due to inactivity label Mar 7, 2026
@ArnaudBarre

Copy link
Copy Markdown
Contributor Author

This PR is still relevant

@github-actions github-actions Bot removed the Resolution: Stale Automatically closed due to inactivity label Mar 9, 2026
@github-actions

github-actions Bot commented Jun 7, 2026

Copy link
Copy Markdown

This pull request has been automatically marked as stale. If this pull request is still relevant, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize reviewing it yet. Your contribution is very much appreciated.

@github-actions github-actions Bot added the Resolution: Stale Automatically closed due to inactivity label Jun 7, 2026
@ArnaudBarre

Copy link
Copy Markdown
Contributor Author

A human decision on the relevance of the PR would be welcomed

@github-actions github-actions Bot removed the Resolution: Stale Automatically closed due to inactivity label Jun 7, 2026
Dunqing added a commit to oxc-project/oxc that referenced this pull request Jun 10, 2026
Port react/react#35318. Hook calls through a nested member
expression such as `FancyHook.property.useNestedThing()` were not
collected into the `$RefreshSig$` custom-hooks list, so components
using them lost state on every fast-refresh update. Resolve the
binding through one extra static member level, matching the Babel
plugin, and force a reset when the root object has no binding.

closes #16571
Dunqing added a commit to oxc-project/oxc that referenced this pull request Jun 11, 2026
Port react/react#35318. Hook calls through a nested member
expression such as `FancyHook.property.useNestedThing()` were not
collected into the `$RefreshSig$` custom-hooks list, so components
using them lost state on every fast-refresh update. Resolve the
binding through one extra static member level, matching the Babel
plugin, and force a reset when the root object has no binding.

closes #16571
graphite-app Bot pushed a commit to oxc-project/oxc that referenced this pull request Jun 12, 2026
…23190)

## Summary

Ports react/react#35318 to the React Refresh plugin: hook calls through a nested member expression such as `FancyHook.property.useNestedThing()` are now collected into the `$RefreshSig$` custom-hooks list, so components using them no longer lose state on every fast-refresh update. As in the Babel plugin, the binding is resolved through one extra static member level, and a force reset is emitted when the root object has no binding in scope. Deeper nesting (`A.B.C.useHook()`) remains uncollected, same as upstream; note that Babel additionally emits `forceReset = true` in that case while oxc does not — a pre-existing, intentional divergence from #6143 that this PR does not change.

closes #16571

## Example

Input:

```jsx
import FancyHook from 'fancy';

export default function App() {
  const foo = FancyHook.property.useNestedThing();
  return <h1>{foo}</h1>;
}
```

Signature before:

```js
_s(App, "useNestedThing{foo}");
```

Signature after:

```js
_s(App, "useNestedThing{foo}", false, function() {
  return [FancyHook.property.useNestedThing];
});
```

---

This PR was prepared with AI assistance; I reviewed, tested, and verified the changes.
camc314 pushed a commit to oxc-project/oxc that referenced this pull request Jul 3, 2026
…23190)

## Summary

Ports react/react#35318 to the React Refresh plugin: hook calls through a nested member expression such as `FancyHook.property.useNestedThing()` are now collected into the `$RefreshSig$` custom-hooks list, so components using them no longer lose state on every fast-refresh update. As in the Babel plugin, the binding is resolved through one extra static member level, and a force reset is emitted when the root object has no binding in scope. Deeper nesting (`A.B.C.useHook()`) remains uncollected, same as upstream; note that Babel additionally emits `forceReset = true` in that case while oxc does not — a pre-existing, intentional divergence from #6143 that this PR does not change.

closes #16571

## Example

Input:

```jsx
import FancyHook from 'fancy';

export default function App() {
  const foo = FancyHook.property.useNestedThing();
  return <h1>{foo}</h1>;
}
```

Signature before:

```js
_s(App, "useNestedThing{foo}");
```

Signature after:

```js
_s(App, "useNestedThing{foo}", false, function() {
  return [FancyHook.property.useNestedThing];
});
```

---

This PR was prepared with AI assistance; I reviewed, tested, and verified the changes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

hooks inside deeply nested objects always cause state reset

3 participants