Skip to content

Conditional JSX children appended instead of replaced on re-render #57

Description

@0xjcf

When using igniteCore with a ternary in the render function that conditionally renders JSX children vs innerHTML, navigating away and back causes the JSX branch to append duplicate children
instead of replacing the previous content.

Reproduction:

const myComponent = igniteCore({
  source: myMachine,
  view: ({ snapshot }) => ({ currentView: snapshot.context.currentView }),
  commands: ({ actor }) => ({
    navigate: (view: string) => actor.send({ type: "NAVIGATE", view }),
  }),
});

myComponent("my-element", (ctx) => {
  return (
    <div>
      {ctx.currentView === "settings" ? (
        <main class="content">
          <h2>Settings</h2>
          <div class="section">
            <h3>Appearance</h3>
            <p>Theme selector here</p>
          </div>
          <div class="section">
            <h3>Authentication</h3>
            <p>Auth status here</p>
          </div>
        </main>
      ) : (
        <main class="content" innerHTML={renderOtherView(ctx.currentView)}></main>
      )}
    </div>
  );
});

Steps:

  1. Navigate to "settings" (JSX branch renders correctly — 2 sections)
  2. Navigate to another view (innerHTML branch renders correctly)
  3. Navigate back to "settings"

Expected: 2 sections (Appearance + Authentication)

Actual: 4 sections (Appearance + Authentication + Authentication + extra content from previous render). Each subsequent navigation adds more duplicates.

Root cause hypothesis: When the ternary switches from the innerHTML branch back to the JSX children branch, the VDOM diff doesn't clear the previous

content before appending the new
children. The innerHTML property is cleared but the previously-rendered JSX children from the first visit are not removed.

Workaround: Use innerHTML with a string template for both branches instead of JSX children for the conditional branch:

Environment:

  • ignite-element version: latest (xstate integration)
  • Renderer: igniteCore with JSX

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions