Lifecycle
Every @beforesemicolon/web-component instance transitions through a series of lifecycle phases, starting from its construction to its destruction and removal from the DOM.
Instead of dealing with native custom element callback names, @beforesemicolon/web-component provides clean, high-level hooks to handle setup, side effects, updates, cleanup, adoption, and runtime errors.
Lifecycle Hook Methods
onMount()
Called when the element is first connected to the DOM. This is the ideal place to run setups such as setting up timers, fetching remote data, or adding event listeners.
- Cleanup function: The
onMount()method can optionally return a cleanup function. If provided, this function is automatically executed when the component is disconnected from the DOM, right beforeonDestroy()is called.
1onMount() {2 console.log('Component is now in the DOM.');3 4 const onResize = () => console.log('Resized');5 window.addEventListener('resize', onResize);6 7 // Return cleanup callback8 return () => {9 window.removeEventListener('resize', onResize);10 };11}onDestroy()
Called when the element is disconnected and removed from the DOM. Use this hook for final cleanups if they were not already handled in the cleanup callback returned by onMount().
1onDestroy() {2 console.log('Component has been removed from the DOM.');3}onUpdate(name, newValue, oldValue)
Called when an observed attribute (declared in static observedAttributes) changes value. This hook runs only after the component is fully mounted.
1onUpdate(name: string, newValue: unknown, oldValue: unknown): void1static observedAttributes = ['theme'];2 3onUpdate(name, newValue, oldValue) {4 if (name === 'theme') {5 console.log(`Theme changed from ${oldValue} to ${newValue}`);6 }7}onAdoption()
Called when the browser's native adoptedCallback() fires, which happens when the custom element is moved to a new document. This is uncommon in most apps, but useful for iframe, portal, document migration, and testing scenarios.
1onAdoption() {2 console.log('Component has been adopted into a new document.');3}onError(error)
Called when WebComponent catches an error from rendering, state updates, stylesheet updates, lifecycle execution, adoption, or cleanup. The default implementation logs the error with console.error.
1onError(error: Error | unknown): void1onError(error) {2 reportError(error)3}Use onError() for component-local error reporting or fallback state. Avoid throwing inside onError() unless you intentionally want the error to escape the component boundary.
Side Effects with effect()
Because WebComponent is powered by Markup, you can use Markup's effect() helper for reactive side effects. An effect runs immediately, tracks any reactive getters it reads synchronously, and runs again when those values change.
Use effect() when the side effect should follow reactive props or state. Keep it out of render() so rendering stays declarative.
1import { WebComponent, effect, html } from '@beforesemicolon/web-component'2 3class SaveStatus extends WebComponent {4 static observedAttributes = ['status']5 6 status = 'idle'7 8 onMount() {9 return effect(() => {10 document.title = `Status: ${this.props.status()}`11 })12 }13 14 render() {15 return html`<p>${this.props.status}</p>`16 }17}The function returned by effect() unsubscribes the effect. Returning it from onMount() ties the effect to the component lifetime, so WebComponent calls it when the element disconnects.
Checking Mount Status
You can check whether the component is currently connected to the DOM using the this.mounted boolean getter.
1get mounted(): booleanThis is particularly useful when performing asynchronous tasks (like fetching data) to prevent updating the state on an unmounted component, which would otherwise throw an error.
1async fetchData() {2 const data = await api.getDetails();3 if (this.mounted) {4 this.setState({ data });5 }6}Lifecycle Order of Execution
Understanding the exact sequence in which callbacks are invoked helps in structuring components properly. The lifecycles run in the following sequence:
constructor
The browser instantiates the element.@beforesemicolon/web-componentmapsstatic observedAttributesto internal reactive props getters and setters, throwing errors if any prop conflicts with reserved keywords.render
Called during the connection phase. The component renders its template and appends it to its content root.stylesheet configuration
Initializes and applies stylesheets (e.g., from thestylesheetproperty or thecsstagged template).onMount
Triggered immediately after rendering is complete and stylesheets are attached. The return value (if it is a function) is cached as the mount cleanup callback.effectcallbacks
Markup effects created duringonMount()run immediately and re-run later when their tracked reactive getters change. If the effect unsubscribe is returned fromonMount(), it becomes the component's mount cleanup callback.onUpdate
Runs every time an observed attribute changes (only while the component is mounted).adoptedCallback/onAdoption
Runs when the browser adopts the element into a different document.Mount Cleanup
Runs the cleanup function returned byonMount()(if any) when the element disconnects.onDestroy
Runs immediately after the mount cleanup function finishes.onError
Runs whenever WebComponent catches an error from one of its guarded rendering, update, stylesheet, lifecycle, adoption, or cleanup paths.