React Refresh Transformer for TypeScript
react-refresh-typescript is a TypeScript transformer that integrates React Fast Refresh (Hot Module Replacement) into React applications. It specifically handles the necessary transformations for TypeScript codebases to enable live editing of React components without losing their state. The package is currently under on-demand maintenance, meaning updates typically occur when issues are opened to track upstream changes in `react-refresh`. It currently matches `react-refresh@0.19.*` (React 19). Its primary audience includes bundler plugin developers, such as those building integrations for webpack, Rollup, or esbuild. Key differentiators include its direct integration as a TypeScript custom transformer, which allows it to operate early in the compilation pipeline, and its support for Deno environments. This package is essential for enabling a smooth developer experience with hot reloading in TypeScript-based React projects.
Common errors
-
Error: `module` must be `es2015` or later.
cause The TypeScript `module` compiler option is set to `CommonJS` or an older value that is not compatible with Fast Refresh transformation.fixChange `compilerOptions.module` in your `tsconfig.json` to `es2015` or a newer ES module target. -
TypeError: (0 , react_refresh_typescript_1.refresh) is not a function
cause Attempting to use `react-refresh-typescript` with a named import when it provides a default export.fixChange your import statement from `import { refresh } from 'react-refresh-typescript';` to `import refresh from 'react-refresh-typescript';`
Warnings
- breaking This transformer does not work with TypeScript `module` option set to `CommonJS`. It requires `es2015` or later.
- gotcha The package is under 'on-demand maintenance', meaning updates to match the latest `react-refresh` runtime may not be immediate. It currently matches `react-refresh@0.19.*`.
- gotcha When using `react-refresh-typescript` in Deno, you must provide a TypeScript instance either via an import map for 'typescript' or by passing `options.ts`.
- gotcha The `refresh()` function should typically be called without arguments when used as a `ts-loader` custom transformer, but it accepts an `Options` object for custom configurations.
Install
-
npm install react-refresh-typescript -
yarn add react-refresh-typescript -
pnpm add react-refresh-typescript
Imports
- refresh
import { refresh } from 'react-refresh-typescript';import refresh from 'react-refresh-typescript';
- Options
import type { Options } from 'react-refresh-typescript'; - require('react-refresh-typescript')
require('react-refresh-typescript')
Quickstart
import refresh from 'react-refresh-typescript';
import ts from 'typescript';
const sourceCode = `
const App = () => {
const [count, setCount] = React.useState(0);
return (
<div>
<h1>Hello Fast Refresh!</h1>
<p>Count: {count}</p>
<button onClick={() => setCount(c => c + 1)}>Increment</button>
</div>
);
};
export default App;
`;
const { outputText } = ts.transpileModule(sourceCode, {
compilerOptions: {
target: ts.ScriptTarget.ESNext,
jsx: ts.JsxEmit.Preserve,
module: ts.ModuleKind.ESNext, // Required for Fast Refresh
},
fileName: 'app.tsx',
transformers: { before: [refresh()] },
});
console.log(outputText);