gotchatypescriptnoneModerate
TypeScript jsx: preserve vs react-jsx Transform
Viewed 0 times
TypeScript 4.1+, React 17+
jsxreact-jsxpreservejsxImportSourceReact 17tsconfig
Error Messages
Problem
TypeScript projects using React 17+ still import React in every file for JSX, or fail to compile because the wrong 'jsx' tsconfig option is set for the bundler.
Solution
Set 'jsx: react-jsx' for React 17+ automatic runtime; 'jsx: preserve' when the bundler handles JSX transform.
// For React 17+ with bundler handling JSX
// (Vite, Create React App, Next.js)
{
"compilerOptions": {
"jsx": "preserve",
"jsxImportSource": "react"
}
}
// For tsc emitting directly (no bundler)
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "react"
}
}
// Options:
// react: Old transform — requires 'import React' in every file
// react-jsx: New transform — no import needed
// react-jsxdev: New transform with dev helpers
// preserve: Leave JSX as-is for bundler to handle
// react-native: Like preserve but with .jsx extension// With jsx: react-jsx or preserve + jsxImportSource
// No need to import React:
function App() {
return <div>Hello</div>; // Works without import React
}Why
React 17 introduced a new JSX transform that automatically imports the JSX runtime, eliminating the manual 'import React' requirement. The tsconfig jsx option must match your build pipeline.
Gotchas
- 'preserve' outputs .jsx files — your bundler must handle the JSX transform. Without a bundler, use 'react-jsx'.
- When using a custom JSX runtime (e.g., Preact, Solid), set jsxImportSource to the appropriate package.
- Mixing 'react' (old) jsx option with React 17+ causes 'React is not defined' errors in some builds.
Revisions (0)
No revisions yet.