Component API
The whole API provided by stencil can be condensed in a set of decorators, lifecycles hooks and rendering methods.
Decorators
Decorators are a pure compiler-time construction used by stencil to collect all the metadata about a component, the properties, attributes and methods it might expose, the events it might emit or even the associated stylesheets. Once all the metadata has been collected, all the decorators are removed from the output, so they don't incur any runtime overhead.
- @Component() declares a new web component
- @Prop() declares an exposed property/attribute
- @State() declares an internal state of the component
- @Watch() declares a hook that runs when a property or state changes
- @Element() declares a reference to the host element
- @Method() declares an exposed public method
- @Event() declares a DOM event the component might emit
- @Listen() listens for DOM events
- @AttrDeserialize() declares a hook to translate a component's attribute string to its JS property
- @PropSerialize() declares a hook that translates a component's JS property to its attribute string
- @AttachInternals() attaches ElementInternals to a component
Lifecycle hooks
- connectedCallback()
- disconnectedCallback()
- componentWillLoad()
- componentDidLoad()
- componentShouldUpdate(changes): boolean
- componentWillRender()
- componentDidRender()
- componentWillUpdate()
- componentDidUpdate()
- render()
componentOnReady()
This isn't a true "lifecycle" method that would be declared on the component class definition, but instead is a utility method that can be used by an implementation consuming your Stencil component to detect when a component has finished its first render cycle.
This method returns a promise which resolves after componentDidRender() on the first render cycle.
componentOnReady() waits for the first render only. Calling it again later returns a promise that's already resolved.
Executing code after componentOnReady() resolves could look something like this:
// Get a reference to the element
const el = document.querySelector('my-component');
el.componentOnReady().then(() => {
// Place any code in here you want to execute when the component is ready
console.log('my-component is ready');
});
The appload event
In addition to component-specific lifecycle hooks, a special event called appload will be emitted when the app (a root level component) and all of its child components have finished loading. You can listen for it on the window object.
The event is emitted once for each root component (one that isn't inside another Stencil component). If you have multiple 'apps' on the same page, you can determine which app emitted the event by checking event.detail.namespace. This will be the value of the namespace config option you've set in your Stencil config.
window.addEventListener('appload', (event) => {
console.log(event.detail.namespace);
});
Other
The following primitives can be imported from the @stencil/core package and used within the lifecycle of a component:
Host:
<Host>, is a functional component that can be used at the root of the render function to set attributes and event listeners to the host element itself. Refer to the Host Element page for usage info.
h() and Fragment:
The JSX factory functions. They're only needed with the legacy JSX setup ("jsx": "react" plus jsxFactory and jsxFragmentFactory in tsconfig.json), where every component file imports them. With Stencil's default setup ("jsxImportSource": "@stencil/core"), JSX and <>...</> fragments work without importing anything.
render():
A utility method to render a virtual DOM created with JSX into a container.
Type: (vnode: VNode, container: Element) => void
Example:
import { render } from '@stencil/core'
const vdom = (
<div className="m-2">Hello World!</div>
)
render(vdom, document.body)
Build:
Flags for the kind of build the code is running in: Build.isDev, Build.isBrowser, Build.isServer and Build.isTesting. Refer to the Build Conditionals page for usage info.
readTask():
Schedules a DOM-read task. The provided callback will be executed in the best moment to perform DOM reads without causing layout thrashing.
Type: (task: Function) => void
writeTask():
Schedules a DOM-write task. The provided callback will be executed in the best moment to perform DOM mutations without causing layout thrashing.
Type: (task: Function) => void
forceUpdate():
Schedules a new render of the given instance or element even if no state changed. Notice forceUpdate() is not synchronous and might perform the DOM render in the next frame.
Type: (ref: any) => void
Example:
import { forceUpdate } from '@stencil/core'
// inside a class component function
forceUpdate(this);
getAssetPath():
Gets the path to local assets. Refer to the Assets page for usage info.
Type: (path: string) => string
Example:
import { Component, Prop, getAssetPath } from '@stencil/core'
@Component({
tag: 'cmp-asset',
})
export class CmpAsset {
@Prop() icon: string;
render() {
return (
<img src={getAssetPath(`assets/icons/${this.icon}.png`)} />
);
}
}
setAssetPath():
Sets the path for Stencil to resolve local assets. Refer to the Assets page for usage info.
Type: (path: string) => string
Example:
import { setAssetPath } from '@stencil/core';
setAssetPath(`{window.location.origin}/`);
setMode():
Sets the style mode of a component. Refer to the Styling page for usage info.
Type: ((elm: HTMLElement) => string | undefined | null) => void
Example:
import { setMode } from '@stencil/core'
// set mode based on a property
setMode((el) => el.getAttribute('mode'));
getMode():
Get the current style mode of your application. Refer to the Styling page for usage info.
Type: (ref: any) => string | undefined
Example:
import { getMode } from '@stencil/core'
getMode(this);
getElement():
Retrieve a Stencil element for a given reference.
Type: (ref: any) => HTMLStencilElement
Example:
import { getElement } from '@stencil/core'
const stencilComponent = getElement(document.querySelector('my-cmp'))
if (stencilComponent) {
stencilComponent.componentOnReady().then(() => { ... })
}
resolveVar():
Because Stencil's decorators rely heavily on static analysis, you cannot use dynamic variables within them. resolveVar provides a deterministic way to find the string value of a given variable at compile time:
Type: (variable: T) => string
Example:
import { Listen, Event, resolveVar } from '@stencil/core`
const COMPONENT_A_EVENT: string = 'componentAEvent';
const EVENTS = {
COMPONENT_B_EVENT: 'componentBEvent',
};
// inside an @Component class
@Component({
tag: 'dynamic-event-names',
})
export class DynamicEventNames {
@Event({ eventName: resolveVar(COMPONENT_A_EVENT) }) myEvent;
@Listen(resolveVar(EVENTS.COMPONENT_B_EVENT))
listenHandler(){
//
}
}
Mixin():
Compose multiple classes into a single constructor using factory functions.
Type:
<TMixins extends readonly MixinFactory[]>(
...mixinFactories: TMixins
): abstract new (...args: any[]) => UnionToIntersection<InstanceType<ReturnType<TMixins[number]>>>;
Example:
import { Mixin, MixedInCtor, Component, Prop, State } from '@stencil/core'
const aFactory = <B extends MixedInCtor>(Base: B) => {
class A extends Base { propA = 'A' };
return A;
}
const bFactory = <B extends MixedInCtor>(Base: B) => {
class B extends Base { @Prop() propB = 'B' };
return B;
}
const cFactory = <B extends MixedInCtor>(Base: B) => {
class C extends Base { @State() propC = 'C' };
return C;
}
@Component({
tag: 'its-mixing-time',
})
export class X extends Mixin(aFactory, bFactory, cFactory) {
render() {
return <div>{this.propA} {this.propB} {this.propC}</div>
}
}
For detailed guidance on using Mixin() to compose behavior into a component, including when to write your own mixin factories versus reactive controllers and using mixins from other Stencil libraries, see the Mixins & Reactive Controllers guide.
setTagTransformer() and transformTag():
Manage tag name transformation at runtime. Refer to the Tag Transformation page for usage info.