Skip to content

Templates

HellaJS has its own flavor of JSX templating, which is similar to React and Solid. It uses a function-based approach to create reactive components.

There’s also an html proxy element that allows you to use HellaJS without a compiler, which is useful when you want to avoid the overhead of a build step.

const Counter = () => {
const count = signal(0);
return (
<button onclick={() => count(count() + 1)}>{count}</button>
);
};
mount(Counter, "#counter");

Components are functions that return a JSX element or an html proxy. Any element that uses a signal or derived function for text content or attributes becomes reactive.

There’s no virtual DOM, and mount is a one-time operation. Components have their own reactive scope and are auto-cleaned when removed.

const Counter = (props, children) => {
// Signals are reactive
const count = signal(props.count);
// Derived functions using signals are also reactive
const doubleCount = () => count() * 2;
const countClass = () => count() % 2 === 0 ? 'even' : 'odd';
return (
{/* Attach functions for reactivity, don't call them */}
<div class={countClass}>
<p>Count: {count}</p>
<p>Double Count: {doubleCount}</p>
<button onclick={() => count(count() + 1)}>{count}</button>
{children}
</div>
);
};
mount(Counter, "#counter");

Since functions make elements dynamic, you can use plain JavaScript conditionals like if or switch—just return an element.

const isShown = signal(true);
//...
<div>
{() => isShown() ? <p>Shown</p> : ""}
</div>

Use the HellaJS forEach function to work with loops.

const items = ['Item 1', 'Item 2', 'Item 3'];
//...
<div>
{forEach(items, (item => <p>{item}</p>))}
</div>

Components are just functions, so you can use them dynamically without any extra modules.

const components = {
profile: () => Profile(props),
settings: () => Settings(props),
};
const active = signal("profile");
//...
<main>
{() => components[active()]}
</main>

Use the html proxy if you want dynamic HTML elements.

const tags = ['div', 'section', 'aside'];
const selectedTag = signal('div');
//...
<main>
{() => html[selectedTag()]("This is dynamic")}
</main>