When to Avoid JSX in React
While JSX is the standard and most popular syntax for building user interfaces in React, there are specific scenarios where bypassing it is beneficial or even necessary. This article explores the key situations where you should avoid JSX in favor of vanilla JavaScript, such as working without a build pipeline, rendering highly dynamic components from runtime data, or authoring lightweight, dependency-free library components.
1. Environments Without a Build Step
JSX is not valid JavaScript; browsers cannot execute it directly. It
must be compiled into standard JavaScript (typically
React.createElement calls) using a tool like Babel, Vite,
or Esbuild. If you are integrating React into a legacy website, a simple
HTML file, or an environment where setting up a bundler and compiler is
impractical, you must avoid JSX. In these scenarios, writing raw
React.createElement allows you to run React directly in the
browser without any build configuration.
2. Generating Components Programmatically from Dynamic Data
If your application generates user interfaces dynamically based on
runtime JSON schemas, configurations, or databases, JSX can become
clunky. Writing deep conditional logic or nested mapping in JSX can
reduce readability. Utilizing React.createElement directly
allows you to loop through data and dynamically instantiate components,
pass props, and define children using standard JavaScript array methods
and object manipulation.
3. Writing Lightweight Library or Widget Code
If you are developing a small, open-source React utility, a micro-frontend, or an embedded widget designed to be consumed by various projects, avoiding JSX can be advantageous. By using raw JavaScript, you eliminate the need to configure a JSX transformer in your library’s build process. This reduces the complexity of your package, minimizes dependency conflicts for your users, and ensures compatibility across different build environments.
4. Creating Highly Abstract Functional Components
For developers utilizing advanced functional programming patterns, JSX’s HTML-like syntax can sometimes obscure the underlying logic. When composing components purely as mathematical functions, higher-order functions, or recursive structures, writing raw JavaScript functions that return element-creation calls can make the flow of data and functional composition much clearer than wrapping everything in visual markup tags.