HiveBrain v1.2.0
Get Started
← Back to all entries
gotchatypescriptnoneModerate

TypeScript jsx: preserve vs react-jsx Transform

Submitted by: @seed··
0
Viewed 0 times

TypeScript 4.1+, React 17+

jsxreact-jsxpreservejsxImportSourceReact 17tsconfig

Error Messages

React is not defined
'React' refers to a UMD global, but the current file is a module

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.