Lifecycle Hooks
PraxisJS components expose four lifecycle hooks — onBeforeMount, onMount, onUnmount, and onError — available on both StatefulComponent and StatelessComponent.
Lifecycle Hooks
All lifecycle hooks are inherited from the base component class, so they're available on both StatefulComponent and StatelessComponent. Override any of them to tap into the component's lifecycle.
Lifecycle diagram
[created] → onBeforeMount() → [DOM rendered] → onMount() → [in use]
↓
onUnmount() → [destroyed]
↑ error ↓
onError(err)onBeforeMount()
Called before the component's DOM is created. The DOM is not yet available at this point.
Use it to initialize state before the first render — for example, setting a @State field from a @Prop value:
@Component()
class Counter extends StatefulComponent {
@Prop() initialCount = 0
@State() count = 0
onBeforeMount() {
this.count = this.initialCount
}
render() {
return <div>{() => this.count}</div>
}
}onMount()
Called after the component is inserted into the DOM. The DOM elements are fully available.
Use it to:
- Access DOM elements captured via
ref - Start timers or intervals
- Subscribe to external events
- Kick off data fetches that require the DOM
@Component()
class Timer extends StatefulComponent {
@State() elapsed = 0
private interval?: ReturnType<typeof setInterval>
onMount() {
this.interval = setInterval(() => this.elapsed++, 1000)
}
onUnmount() {
clearInterval(this.interval)
}
render() {
return <p>{() => this.elapsed}s elapsed</p>
}
}onUnmount()
Called when the component is removed from the DOM. Clean up everything you set up in onMount:
onMount() {
this.interval = setInterval(() => this.tick(), 1000)
window.addEventListener('resize', this.onResize)
this.observer = new ResizeObserver(this.handleResize)
this.observer.observe(this.el)
}
onUnmount() {
clearInterval(this.interval)
window.removeEventListener('resize', this.onResize)
this.observer.disconnect()
}Composables clean up automatically
If you're using @Compose with a composable like WindowSize or ScrollPosition, you don't need to manually clean up — composables hook into onMount and onUnmount automatically.
onError(error)
Called when an error is thrown inside the component or its children. Use it to display fallback UI without crashing the whole tree.
@Component()
class SafeLoader extends StatefulComponent {
@State() error: Error | null = null
onError(err: Error) {
this.error = err
console.error('Component error:', err)
}
render() {
return () => this.error
? <p class="error">Something went wrong: {() => this.error!.message}</p>
: <DataView />
}
}Lifecycle in StatelessComponent
Lifecycle hooks work the same way in StatelessComponent — no @State required:
@Component()
class Banner extends StatelessComponent<{ text: string }> {
onMount() {
console.log('Banner mounted with text:', this.props.text)
}
onUnmount() {
console.log('Banner removed')
}
render() {
return <div class="banner">{this.props.text}</div>
}
}Combining lifecycle with @Watch
@Watch runs after mount automatically. Use onMount when you need DOM access first:
@Component()
class AutoFocus extends StatefulComponent {
private inputEl: HTMLInputElement | null = null
onMount() {
this.inputEl?.focus()
}
render() {
return <input ref={(el) => { this.inputEl = el }} />
}
}What's next?
- Async Data — data fetching with
@Resourceand reactive refetching - Decorators: Watchers —
@Watch,@When,@Untilfor reactive side effects - Composables: DOM —
WindowSize,ScrollPosition, and more — all lifecycle-managed automatically
JSX Syntax
PraxisJS uses a custom JSX runtime. Learn how to write reactive templates, handle events, use fragments, and map lists.
Async Data
@Resource is PraxisJS's decorator for binding async data to a component field — it tracks loading, error, and data state reactively, with automatic refetch, cancel, and mutate.