DEV Community

Cover image for State.js Event System - The Complete Beginner’s Guide
iDev-Games
iDev-Games

Posted on

State.js Event System - The Complete Beginner’s Guide

State.js introduces a new way to build reactive UI:

HTML holds the data.

CSS reacts to the data.

Events change the data.

This tutorial explains how State.js listens to events, how you trigger state changes, and how to build interactive UI without writing JavaScript logic.


⭐ 1. What Is a State.js Event?

A State.js event is simply:

  • a DOM event (click, input, mouseover, keydown, etc.)
  • connected to a state mutation
  • written declaratively in HTML

Example:

<div data-state
     data-count="0"
     data-state-on="click => count += 1"
     data-state-text="Count: {count}">
</div>
Enter fullscreen mode Exit fullscreen mode

When you click the element:

  • count increases
  • State.js updates the attribute
  • CSS variables update
  • the text updates

All without JavaScript logic.

Learn more: State.js triggers


⭐ 2. The data-state-on Attribute

This is the core of the event system.

<div data-state
     data-active="false"
     data-state-on="click => active = !active">
</div>
Enter fullscreen mode Exit fullscreen mode

This toggles the data-active attribute every time the element is clicked.

State.js then:

  • updates CSS variables
  • updates any bound text
  • updates any reactive classes

⭐ 3. Listening to Any DOM Event

You can listen to any event the browser supports.

Click

data-state-on="click => count += 1"
Enter fullscreen mode Exit fullscreen mode

Input

data-state-on="input => value = event.target.value"
Enter fullscreen mode Exit fullscreen mode

Mouseover

data-state-on="mouseover => hovered = true"
Enter fullscreen mode Exit fullscreen mode

Mouseout

data-state-on="mouseout => hovered = false"
Enter fullscreen mode Exit fullscreen mode

Keydown

data-state-on="keydown => key = event.key"
Enter fullscreen mode Exit fullscreen mode

State.js doesn’t invent new events — it uses the browser’s native ones.

Learn more: Event expressions


⭐ 4. Using Event Data (event)

State.js exposes the event object as event.

Example: capture the clicked element’s text.

<div data-state
     data-last=""
     data-state-on="click => last = event.target.textContent"
     data-state-text="Last clicked: {last}">
</div>
Enter fullscreen mode Exit fullscreen mode

Example: track mouse position.

<div data-state
     data-x="0"
     data-y="0"
     data-state-on="mousemove => x = event.clientX; y = event.clientY"
     data-state-text="X: {x}, Y: {y}">
</div>
Enter fullscreen mode Exit fullscreen mode

⭐ 5. Updating Another Element’s State

Use data-state-target to update a different element.

<button
  data-state-trigger
  data-state-target="#box"
  data-state-on="click => color = 'red'">
  Make Red
</button>

<div id="box"
     data-state
     data-color="blue"
     data-state-class="red: color == 'red'">
</div>
Enter fullscreen mode Exit fullscreen mode

This is the State.js equivalent of:

  • React props
  • Vue emits
  • Svelte dispatch

But simpler.


⭐ 6. Multiple Event Handlers

You can chain multiple events:

<div data-state
     data-state-on="
       click => count += 1;
       mouseover => hovered = true;
       mouseout => hovered = false
     ">
</div>
Enter fullscreen mode Exit fullscreen mode

Each event runs its own expression.


⭐ 7. Using Events to Add/Remove Classes

<div data-state
     data-active="false"
     data-state-on="click => active = !active"
     data-state-class="active: active">
</div>
Enter fullscreen mode Exit fullscreen mode

This toggles a class with no JavaScript.


⭐ 8. Using Events to Drive CSS Animations

<div data-state
     data-state-on="click => animate = true"
     data-state-class="pop: animate">
</div>
Enter fullscreen mode Exit fullscreen mode

CSS:

.pop {
  animation: pop 0.3s ease;
}
Enter fullscreen mode Exit fullscreen mode

This is how you build interactive UI without JS logic.


⭐ 9. Building a Mini App with Events

<div id="app"
     data-state
     data-count="0"
     data-state-on="click => count += 1"
     data-state-text="Clicked {count} times">
</div>
Enter fullscreen mode Exit fullscreen mode

This is a complete app:

  • reactive state
  • reactive text
  • event-driven logic
  • no JavaScript

This is the State.js mental model.


⭐ 10. Why the Event System Matters

Because it replaces:

  • React’s onClick={() => setCount(count + 1)}
  • Vue’s @click="count++"
  • Svelte’s on:click={() => count++}

With:

data-state-on="click => count += 1"
Enter fullscreen mode Exit fullscreen mode

No JS.

No framework.

No re-renders.

No hydration.

No build step.

This is the State.js philosophy.

Learn more: State.js architecture

Top comments (0)