Stateful Components
Stateful Components
Use StatefulComponent when your component needs to manage internal state.
The component initializes state from props, then re-renders whenever state changes.
Live counter
This is a real Preactile component rendered live in your browser. Click the buttons:
import preactile.*
object Counter extends StatefulComponent[Unit, Int]:
override def initialState(props: Unit): Int = 0
def render(props: Unit, state: Int, instance: Instance): VNode =
E.div(
A.`class`("counter-demo"),
E.button(A.onClick(_ => instance.setState(state - 1)), "-"),
E.span(" ", E.strong(state.toString), " "),
E.button(A.onClick(_ => instance.setState(state + 1)), "+"),
)
end CounterThis example runs in your browser; enable JavaScript to see it.
Key points:
initialStatederives the starting state from props (called once on mount)renderreceives both current props and current state as argumentsinstance.setState(newState)triggers a re-render with the updated state
State derived from props
Initial state can depend on incoming props:
import preactile.*
case class TimerProps(initialDelayMs: Int)
object Timer extends StatefulComponent[TimerProps, Int]:
override def initialState(props: TimerProps): Int = props.initialDelayMs
def render(props: TimerProps, state: Int, instance: Instance): VNode =
E.div(
E.span(s"Elapsed: ${state}ms"),
E.button(A.onClick(_ => instance.setState(0)), "Reset"),
)
Lifecycle hooks
StatefulComponent provides lifecycle hooks for side effects. didMount runs after
the first render; willUnMount is the place to drop timers or subscriptions:
import preactile.*
object DataFetcher extends StatefulComponent[Unit, String]:
override def initialState(props: Unit): String = "Loading..."
override def didMount(instance: Instance): Unit =
instance.setState("Data loaded!")
override def willUnMount(instance: Instance): Unit =
()
def render(props: Unit, state: String, instance: Instance): VNode =
E.p(state)
See the Examples page for the other live demos.