Back to Home

Today I Learned

A collection of short notes from my cross-disciplinary studies, shared as I learn in public.

status: In Progress

Status Indicator

The status indicator reflects the current state of the work: - Abandoned: Work that has been discontinued - Notes: Initial collections of thoughts and references - Draft: Early structured version with a central thesis - In Progress: Well-developed work actively being refined - Finished: Completed work with no planned major changes This helps readers understand the maturity and completeness of the content.

·
certainty: certain

Confidence Rating

The confidence tag expresses how well-supported the content is, or how likely its overall ideas are right. This uses a scale from "impossible" to "certain", based on the Kesselman List of Estimative Words: 1. "certain" 2. "highly likely" 3. "likely" 4. "possible" 5. "unlikely" 6. "highly unlikely" 7. "remote" 8. "impossible" Even ideas that seem unlikely may be worth exploring if their potential impact is significant enough.

·
importance: 7/10

Importance Rating

The importance rating distinguishes between trivial topics and those which might change your life. Using a scale from 0-10, content is ranked based on its potential impact on: - the reader - the intended audience - the world at large For example, topics about fundamental research or transformative technologies would rank 9-10, while personal reflections or minor experiments might rank 0-1.

Topics
Showing single entry
March 2026
posted on 03.29.2026

HTML Button Nesting Causes Hydration Errors

In HTML, <button> cannot be a descendant of another <button>. Browsers silently restructure the DOM when they encounter this, but React's server-rendered HTML does not match the browser's restructured DOM, causing a hydration mismatch.

// BAD: nested button causes hydration error
<button onClick={openMenu}>
  <Icon />
  {isOpen && (
    <div className="submenu">
      <button onClick={selectOption}>Option A</button>  {/* nested! */}
    </div>
  )}
</button>
// GOOD: move submenu outside the button, wrap both in a div
<div onMouseEnter={showMenu} onMouseLeave={hideMenu}>
  <button onClick={openMenu}>
    <Icon />
  </button>
  {isOpen && (
    <div className="submenu">
      <button onClick={selectOption}>Option A</button>
    </div>
  )}
</div>

The error message in Next.js dev mode is: In HTML, <button> cannot be a descendant of <button>. This will cause a hydration error.

This also applies to <a> inside <a>, <form> inside <form>, and other elements with restrictions defined in the HTML spec's content model.

No reactions yet

in Naperville, IL
Last visitor from Mitaka, Japan