8 Challenges I Faced Building a Complex Visual Editor in React

Published: (February 16, 2026 at 10:06 AM EST)
5 min read
Source: Dev.to

Source: Dev.to

Overview

Editing LaTeX as raw strings is a nightmare for beginners. That’s why I built BlockTeXu — a block‑based visual LaTeX equation editor where you snap together math symbols like LEGO blocks, and it generates valid LaTeX automatically.

Along the way, I ran into a number of challenges that are broadly useful in React development: recursive components, immutable tree operations, Drag & Drop, and more. This article gives an overview of the 8 technical challenges I faced and how I approached them. I’ll dive deeper into each topic in upcoming posts.


Core LaTeX Generation

The core mechanism generates LaTeX from a tree of PlacedBlock nodes.

function generateBlockLatex(block: PlacedBlock): string {
  let latex = block.definition.latex;

  for (let i = 0; i  0) {
      slotLatex = slotBlocks.map(b => generateBlockLatex(b)).join(' ');
    } else {
      slotLatex = block.rawValues[i] || '\\square';
    }

    latex = latex.replace('□', slotLatex);
  }

  return latex;
}
  • Each block’s definition.latex holds a template (e.g. \frac{□}{□}), and the placeholder is replaced sequentially with the results from child nodes.
  • Because the templates guarantee correct syntax, this approach structurally prevents LaTeX syntax errors.

The mechanism is simple, but implementing the actual UI, interactions, and output revealed several React‑specific challenges.


Technical Challenges

Problem 1 – Representing a Tree‑Structured UI with React

In BlockTeXu the UI is essentially a visual representation of an Abstract Syntax Tree (AST). I implemented this using a recursive pattern:

PlacedBlock → BlockSlot → PlacedBlock
PlacedBlock (Fraction)
├── BlockSlot[0] (Numerator)
│   └── PlacedBlock (Integral)
│       ├── BlockSlot[0] (Lower bound)
│       └── BlockSlot[1] (Upper bound)
└── BlockSlot[1] (Denominator)
    └── PlacedBlock (Variable y)
  • Key Insight: To prevent infinite UI scaling, I used a depth prop to dynamically adjust CSS scales and font sizes.
  • Managing Drag & Drop across these nested boundaries was one of the trickiest parts.

Next post: “Designing Recursive Components in React — Implementing Nested Math Structures”


Problem 2 – Updating a Node at Arbitrary Depth While Preserving Immutability

When a user adds a block to a slot, we must update a node at any depth in the tree. I wrote a recursive function updateBlockInTree that creates new objects only along the path to the target node, leaving all other references unchanged.

  • This immutability enables a simple undo/redo implementation by storing the state history as an array.

Next post: Covered in detail in the recursive components article


Problem 3 – Stale Closures in Keyboard Handlers

Registering a handler with window.addEventListener('keydown', handler) inside useEffect traps the state in the closure from the time it was registered.

Solution in BlockTeXu:

  • Convert the stale state (pendingAction, selectedStockIndex) from useState to useRef.
  • The handler now reads the latest values synchronously.

Next post: “Solving the Stale Closure Problem in Keyboard Handlers with useRef”


Problem 4 – KaTeX‑Rendered Equations Exported as Images Lose Text

html-to-image uses an SVG foreignObject to convert the DOM to an image, but KaTeX’s web fonts (@font-face) aren’t embedded correctly, resulting in blank images.

Attempts:

  1. Wait for document.fonts.ready.
  2. Call toPng twice (the first call primes the font cache).
  3. Consider switching to html2canvas.

Next post: “The Web Font Problem When Exporting KaTeX Equations as Images”


Problem 5 – Supporting Both Palette‑Add and Workspace‑Reorder Drag & Drop

  • The design stores the block definition JSON in the dataTransfer of the HTML5 Drag & Drop API.
  • To differentiate adding new blocks (palette → workspace) from reordering (within workspace), the transferred data includes a { reorder: true, index } flag.
  • Drops into nested slots are also supported, making event bubbling control (stopPropagation) essential.

Next post: “Design Patterns for Building a Block Editor with HTML5 Drag & Drop”


Problem 6 – Quickly Finding the Right Block Among 216 Options

  • Use useMemo to control recalculation.
  • Separate category selection state from search state.
  • During a search, all blocks across every category are included; clearing the search returns to category‑based browsing.

Problem 7 – Vercel Build Fails Even Though It Works Locally

  • Vite build failures caused by non‑ASCII characters in Windows file paths (e.g., OneDrive/Desktop).
  • Linux file‑permission errors from committing node_modules to Git.

Next post: “Pitfalls When Deploying a Vite + React App to Vercel”


Problem 8 – SEO for a React SPA

  • Embedded meta descriptions, OGP tags, Twitter Cards, JSON‑LD structured data, sitemap.xml, and robots.txt in the static HTML.
  • Manually requested indexing via Google Search Console.
  • Googlebot can execute JavaScript, so SPAs can be indexed, but providing information in the initial HTML improves reliability.

Next post: “A Complete Guide to SEO for a Personal Dev Tool SPA”


Quick Reference Table

#TopicSummary
3Recursive component designPlacedBlock → BlockSlot recursion, depth management, immutable tree updates
4Stale closure in keyboard handlersuseRef synchronization pattern, pendingAction design
5KaTeX image export font issuesHow html-to-image works, double rendering, html2canvas comparison
6Block editor with Drag & DropdataTransfer design

Stay tuned for the deeper dives!

7. Vercel deployment pitfalls

  • Non‑ASCII path issues
  • node_modules permission errors
  • Build commands

8. SEO for SPAs

  • Complete setup of meta / OGP / JSON‑LD / Search Console

  • Nested drops, bubbling control

Recursive components, immutable tree operations, Drag & Drop, web‑font image rendering — building a single editor touched on a surprisingly wide range of React topics.
I’ll be sharing implementation code and lessons learned for each topic in upcoming posts.

If you’re interested in recursive UI or tree‑operation design, I’d love to hear your thoughts in the comments. And if you’d like to try BlockTeXu yourself, check it out at blocktexu.com/en.

0 views
Back to Blog

Related posts

Read more »