← All posts

Programming 4 min read

The JSX Series (Part 1) How we escaped Spaghetti code

How JSX solved string soup, context switching, and fragile DOM manipulation in modern web development.

The JSX Series (Part 1) How we escaped Spaghetti code

Try finding the missing quote in this function:

JavaScript


function renderTodoList() {
  var name = "Edward Phillips";
  var container = document.getElementById("todo-app");
  var htmlString = "";
  
  htmlString += "<h1>" + name + "'s Todo List</h1>";
  htmlString += "<ul style='list-style-type: none; padding: 0;'>";
  
  for (var i = 0; i < todoList.length; i++) {
    htmlString += "<li style='text-decoration: none;'>" + todoList[i] + "</li>";
  }
  
  htmlString += "</ul>";
  container.innerHTML = htmlString;
}

Building UI using Spaghetti code

In my first job as a software developer, I was thrown right into the deep end of legacy web development. I had to maintain massive, thousands-of-lines-of-code files where HTML, CSS, and JavaScript were all mashed together.

The workflow was chaotic: we would make an AJAX request, fetch some JSON data, and then use vanilla JavaScript to manually build and inject HTML and CSS directly into the DOM based on that data.

Hard to read, a nightmare to maintain

This setup was incredibly fragile. Because the entire UI was constructed using raw string concatenation, missing a single quote or misplacing an angle bracket would introduce subtle bugs that took hours to track down.

To make matters worse, code editors were practically useless. IDEs treat text inside quotes as plain strings, so we lost syntax highlighting, auto-completion, and tag matching for HTML or CSS. Everything was trapped inside a single "string soup."

Verbose DOM Manipulation

To avoid the risks of string concatenation, the alternative was using native DOM manipulation methods like document.createElement(), setAttribute(), and appendChild():

JavaScript


// Safe from quote collisions, but 6 lines of code for one list item
var ul = document.createElement("ul");
var li = document.createElement("li");
li.style.color = color;
li.textContent = text;
ul.appendChild(li);
container.appendChild(ul);

While this approach completely eliminates quote-collision bugs, it comes with a major tradeoff: excessive boilerplate. Writing six lines of repetitive setup code just to render a simple list item quickly becomes tedious and hard to read.

Developers were stuck in a dilemma: we needed a way to avoid the dangers of string concatenation without drowning in repetitive, line-by-line DOM manipulation.

Separate HTML Templates as a solution

To bring sanity back to our codebase, the industry moved toward separating HTML templates and JavaScript files.

While this was a huge step forward for readability, it introduced a new pain point: constant context switching. A button isn't just static HTML—it has click handlers, disabled states, and dynamic styles. Splitting a single feature across .html markup files, .js logic files, and .css style files meant jumping back and forth just to make one change.

JSX - Code-Habitation as an even better solution

JSX asked a radical question: What if everything related to a single feature lived in the exact same file?

Instead of separating code by file type (.html, .js, .css), JSX advocates for keeping related code together by component. If you build a button, it makes total sense to keep its markup, click handlers, and styling logic all in one place.

JSX solves the string soup problem by providing a clean, declarative syntax that lets you mix HTML markup directly inside JavaScript—giving you full syntax highlighting, editor linting, and no more jumping between files.


Example: The Same Todo List in Modern JSX

TypeScript


const todoList = ["Learn React", "Learn TypeScript", "Build a React App"];

export const TodoList = () => {
  const name = "Edward Phillips";

  return (
    <>
      <h1>{`${name}'s`} Todo List</h1>
      <ul style={{ listStyleType: "none", padding: 0 }}>
        {todoList.map((item, index) => (
          <TodoItem key={index} item={item} />
        ))}
      </ul>
    </>
  );
};

const TodoItem = ({ item }: { item: string }) => {
  return <li style={{ textDecoration: "none" }}>{item}</li>;
};

So, What IS JSX?

  • It's Not React: JSX is its own standalone syntax extension for JavaScript (React just uses it to describe UI).

  • It's Syntax, Not Strings: JSX lets you write HTML-like markup directly inside JavaScript without quotes or string concatenation.

  • It Evaluates to an Object: Every JSX element evaluates to a plain JavaScript object that describes a UI node (<button>, <TodoList/>, or <>...</>).

  • Best of Both Worlds: You get the visual clarity of HTML alongside the full programmatic power of JavaScript (loops, conditions, and variables).

Why JSX Changed the Game

  • Readability and Maintainability: JSX eliminates imperative DOM construction methods like document.createElement(). You describe what the UI should look like, not how to manually append nodes string by string.

  • All Feature Code in One Place: JSX accepts that UI layout and UI logic are naturally connected. Bringing both into the same component file keeps your code focused, modular, and easy to maintain without context switching.