Components

Components

Preactile components are the building blocks of your UI. There are two main types: stateless (Component) and stateful (StatefulComponent).

Stateless components

Use Component when your output depends only on its props:

import preactile.*

object Greeting extends Component[String]:
  def render(props: String): VNode = E.h1(s"Hello, $props!")

Compose them like any other element:

import preactile.*

object App extends Component[Unit]:
  def render(props: Unit): VNode = E.div(
    Greeting("Alice"),
    Greeting("Bob"),
  )

Components with typed props

Define a case class for complex prop types:

import preactile.*

case class ButtonProps(label: String, onClick: () => Unit)

object Button extends Component[ButtonProps]:
  def render(props: ButtonProps): VNode = E.button(
    A.`class`("btn"),
    A.onClick(_ => props.onClick()),
    props.label,
  )

Live demo: component composition

This shows a typed Button component composed inside an App that manages click count state:

import preactile.*

case class ButtonProps(label: String, onClick: () => Unit)

object Button extends Component[ButtonProps]:
  def render(props: ButtonProps): VNode = E.button(
    A.`class`("demo-button"),
    A.onClick(_ => props.onClick()),
    props.label,
  )

object App extends StatefulComponent[Unit, Int]:
  override def initialState(props: Unit): Int = 0

  def render(props: Unit, state: Int, instance: Instance): VNode = E.div(
    A.`class`("components-demo"),
    E.p(s"Button clicked $state times."),
    Button(ButtonProps("Click me!", () => instance.setState(state + 1))),
  )

This example runs in your browser; enable JavaScript to see it.

The ButtonProps case class gives you full type safety for props, and the parent component passes a callback that updates its own state.

See Stateful Components for setState, and Examples for the other live demos.