NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
npm · #1105 most downloaded on npm
Validate that your components can safely be updated with Fast Refresh
Last release 20 days ago
14 Sep 2026
Release timing varies
gaps range from 8 days to 4 months
Nearly every release is documented
notes for 43 of 43 stable releases
1 version withdrawn
withdrawn after publishing
5 years old
47 releases · first in 2022
Add allowCompoundComponents option
allowCompoundComponents option (#117)Default:
false(trueinviteconfig)
Don't warn when components are exported as an object gathering them. Every member of the object must be a component, and a member holding an anonymous function requires a component name as key.
This should be enabled if the fast refresh implementation correctly handles this case. Vite supports it since @vitejs/plugin-react 4.7.0, @vitejs/plugin-react-swc 3.11.0.
{
"react-refresh/only-export-components": [
"error",
{ "allowCompoundComponents": true }
]
}Enabling this option allows code such as the following:
const Root = () => <></>;
const Label = () => <></>;
export const Tag = { Root, Label };One column per quarter.
Support re-exporting namespace components (fixes #116 )
Fix SCREAMING_SNAKE_CASE constant exported via export { Name } incorrectly treated as React component #114 (fixes #113 )
Add instant to allowExportNames in Next config #112
instant to allowExportNames in Next config #112Fix check for non component class exported via export { } #110 (fixes #109 )
Support nested function calls for extraHOCs (actually fixes #104 )
Support false positives with TypeScript function overloading (fixes #105 )
The package now ships as ESM and requires ESLint 9 + node 20. Because legacy config doesn't support ESM, this requires to use flat config
reactRefresh export is available and prefered over the default export. It's an object with two properties:
plugin: The plugin object with the rulesconfigs: An object containing configuration presets, each exposed as a function. These functions accept your custom options, merge them with sensible defaults for that config, and return the final config object.customHOCs option was renamed to extraHOCsextraHOCs option (like connect or styled)Config example:
import { defineConfig } from "eslint/config";
import { reactRefresh } from "eslint-plugin-react-refresh";
export default defineConfig(
/* Main config */
reactRefresh.configs.vite({ extraHOCs: ["someLibHOC"] }),
);Config example without config:
import { defineConfig } from "eslint/config";
import { reactRefresh } from "eslint-plugin-react-refresh";
export default defineConfig({
files: ["**/*.ts", "**/*.tsx"],
plugins: {
// other plugins
"react-refresh": reactRefresh.plugin,
},
rules: {
// other rules
"react-refresh/only-export-components": [
"warn",
{ extraHOCs: ["someLibHOC"] },
],
},
});This version follows a revamp of the internal logic to better make the difference between random call expressions like export const Enum = Object.keys(Record) and actual React HOC calls like export const MemoComponent = memo(Component). (fixes #93)
The rule now handles ternaries and patterns like export default customHOC(props)(Component) which makes it able to correctly support files like this one given this config:
{
"react-refresh/only-export-components": [
"warn",
{ "extraHOCs": ["createRootRouteWithContext"] }
]
}Note
Actually createRoute functions from TanStack Router are not React HOCs, they return route objects that fake to be a memoized component but are not. When only doing createRootRoute({ component: Foo }), HMR will work fine, but as soon as you add a prop to the options that is not a React component, HMR will not work. I would recommend to avoid adding any TanStack function to extraHOCs it you want to preserve good HMR in the long term. Bluesky thread.
Because I'm not 100% sure this new logic doesn't introduce any false positive, this is done in a major-like version. This also give me the occasion to remove the hardcoded connect from the rule. If you are using connect from react-redux, you should now add it to extraHOCs like this:
{
"react-refresh/only-export-components": ["warn", { "extraHOCs": ["connect"] }]
}Nothing published for this version
Nothing published for this version
Nothing published for this version
Revert changes to fix #93 (fixes #95 )
Report cases like export const ENUM = Object.keys(TABLE) as EnumType[]; (fixes #93 )
Add "generateImageMetadata" , "generateSitemaps" & "generateStaticParams" to allowExportNames in Next config
"generateImageMetadata", "generateSitemaps" & "generateStaticParams" to allowExportNames in Next config"generateImageMetadata", "generateSitemaps" & "generateStaticParams" to allowExportNames in Next configAdd "metadata" , "generateMetadata" & "generateViewport" to allowExportNames in Next config
"metadata", "generateMetadata" & "generateViewport" to allowExportNames in Next config"metadata", "generateMetadata" & "generateViewport" to allowExportNames in Next configAdd "viewport" to allowExportNames in Next config
"viewport" to allowExportNames in Next config (#89)This allows exports like fetchCache and revalidate which are used in Page or Layout components and don't trigger a full page reload.
This allows exports like fetchCache and revalidate which are used in Page or Layout components and don't trigger a full page reload.
import reactRefresh from "eslint-plugin-react-refresh";
export default [
/* Main config */
reactRefresh.configs.next,
];
Don't warn on nested HOC calls (fixes #79)
Add name to configs for ESLint Config Inspector
Add name to configs for ESLint Config Inspector
ESM/CJS interop is the worse that happened to this ecosystem, this is all I have to say.
ESM/CJS interop is the worse that happened to this ecosystem, this is all I have to say.
Fix detection of local components to not generate warning on for variable inside JSX files that follow React component naming (fixes #75)
.default property access under TS node16 module resolution (fixes #70)Fix CJS/ESM interop issue. Sorry everyone for the trouble.
Fix CJS/ESM interop issue. Sorry everyone for the trouble.
This was actually done by mistake in the previous release when moving from a deprecated API to a new one.
By default, the rule only knows that memo & forwardRef function calls with return a React component. With this option, you can also allow extra function names like Mobx observer to make this code valid:
const Foo = () => <></>;
export default observer(Foo);
{
"react-refresh/only-export-components": [
"error",
{ "customHOCs": ["observer"] }
]
}
Thanks @HorusGoul!
You can now add the recommended config to your ESLint config like this:
import reactRefresh from "eslint-plugin-react-refresh";
export default [
/* Main config */
reactRefresh.configs.recommended, // Or reactRefresh.configs.vite for Vite users
];
To follow ESLint recommandations, the rule is added with the error severity.
Some simple types ensure that people typecheking their config won't need @ts-expect-error anymore.
This was actually done by mistake in the previous release when moving from a deprecated API to a new one.
Given that ESLint 8 is officialy end-of-life and the only report (#56) didn't get likes, I'm going forward and documenting the expected minimum version from ESLin in the package JSON so that people can get warning from their package manager.
Warn if a context is exported alongside a component (fixes #53). Thanks @IgorAufricht!
Support for react-redux connect (export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)) (fixes #51)
react-redux connect (export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)) (fixes #51)Support type assertion on default export (fixes #48)
Ignore type exports (ex. export type foo = string;) (fixes #47)
export type foo = string;) (fixes #47)Support function Foo() {}; export default React.memo(Foo) (#46) (thanks @SukkaW!)
function Foo() {}; export default React.memo(Foo) (#46) (thanks @SukkaW!)Support function Foo() {}; export default memo(Foo) (fixes #44) (thanks @SukkaW!)
function Foo() {}; export default memo(Foo) (fixes #44) (thanks @SukkaW!)Support export const foo = -1 with allowConstantExport (fixes #43)
export const foo = -1 with allowConstantExport (fixes #43)Support export { Component as default } (fixes #41)
export { Component as default } (fixes #41)- Ignore cypress test files
Allow TaggedTemplateExpression for styled components (fixes #32)
TaggedTemplateExpression for styled components (fixes #32)Add allowExportNames option (fixes #29)
allowExportNames option (fixes #29)Add warning for TS enums exports
Fix typos in messages (#15, #16). Thanks @adamschachne & @janikga!
Ignore export type * (fixes #12)
export type * (fixes #12)This option allow to don't warn when a constant (string, number, boolean, templateLiteral) is exported aside one or more components.
allowConstantExport option (fixes #8)This option allow to don't warn when a constant (string, number, boolean, templateLiteral) is exported aside one or more components.
This should be enabled if the fast refresh implementation correctly handles this case (HMR when the constant doesn't change, propagate update to importers when the constant changes). Vite supports it, PR welcome if you notice other integrations works well.
This only works when using direct export. So this pattern doesn't warn anymore:
export const CMS = () => <></>;
But this one will still warn:
const CMS = () => <></>;
export default CMS;
Ignore stories files (*.stories.*) (Fixes #10)
Ignore stories files (*.stories.*) (Fixes #10)
Report default CallExpression exports (#7) (Fixes #6)
Report default CallExpression exports (#7) (Fixes #6)
This allows to report a warning for this kind of patterns that creates anonymous components:
export default compose()(MainComponent)
Add checkJS option (#5) (Fixes #4)
Add checkJS option (#5) (Fixes #4)
Ignore test files (*.test.*, *.spec.*) (Fixes #2)
Ignore test files (*.test.*, *.spec.*) (Fixes #2)
Allow numbers in component names (Fixes #1)
Allow numbers in component names (Fixes #1)
Report an error when a file that contains components that can't be fast-refreshed because:
Report an error when a file that contains components that can't be fast-refreshed because:
Doc only: Update limitations section README.md
Doc only: Update limitations section README.md
- Fix TS import - Document limitations
Initial release
Initial release
Your coding agent can read these notes before it upgrades. Set up the MCP server →