Rendering
Conditional Rendering
Use && for conditional blocks:
{step === 1 && <StepOne onContinue={() => store.setStep(2)} />}
{step === 2 && <StepTwo onBack={() => store.setStep(1)} />}Use ternary for either/or:
{!paymentComplete
? <PaymentForm onPay={handlePay} />
: <div class="success">Payment complete</div>
}Under the hood, conditional children are compiled into <template> markers with swap logic — no wasted DOM nodes when the condition is false.
List Rendering
Use .map() with a key prop to render arrays:
<ul>
{todos.map(todo => (
<TodoItem
key={todo.id}
todo={todo}
onToggle={() => store.toggle(todo.id)}
onRemove={() => store.remove(todo.id)}
/>
))}
</ul>The key prop is required for efficient list diffing. Gea uses applyListChanges internally to handle:
- Append — new items added to the end
- Delete — items removed from any position
- Add — items inserted at any position
- Reorder — items moved (e.g., after
sort) - Swap — two items exchanged positions
Only the DOM nodes that actually changed are touched — unchanged items stay in place.
Callbacks inside .map() use event delegation. The framework resolves which array item was targeted using data-gea-item-id attributes that the Vite plugin generates automatically.
Initial Rendering
Components are instantiated with new and inserted into the DOM with .render():
import App from './app'
const app = new App()
app.render(document.getElementById('app'))The render(rootEl, index?) method:
- Evaluates the
template()method to produce an HTML string - Parses that string into a DOM element
- Inserts it into the given parent element
- Sets up reactive observers for all state paths used in the template
After the initial render, the component never re-renders its entire template. State changes trigger surgical patches — only the specific DOM nodes that depend on the changed state paths are updated.
