I want a parent component to manage a central state of the application and pass down the relevant information to its children, re-rendering them as needed. This is how I understood parent/child communication in Stencil - the parents send data to the children via properties and the children send data to the parent via events. Is this assumption wrong?
I am having trouble finding a relevant example online that does not reference React-specific API's
Edit: It may be relevant that, in my case, the parent is rendering a wrapper component with a slot. Code sample updated to reflect that...
Simplified Example:
parent.tsx:
// Parent Component
import { Component, State, Listen, h } from '@stencil/core';
@Component({
tag: 'parent',
styleUrl: 'parent.css',
})
export class Parent {
@State() selectedFeature: any = null;
@Listen('featureClicked', { target: 'body' })
updateSelectedFeature(e: CustomEvent) {
this.selectedFeature = e.detail;
}
render() {
return [
<wrapper>
<child slot="content" selected-feature={this.selectedFeature}></child>
</wrapper>,
// ...other components
];
}
}
child.tsx:
// Child Component
import { Component, Prop, h } from '@stencil/core';
@Component({
tag: 'child',
styleUrl: 'child.css',
})
export class Child {
@Prop() selectedFeature!: any;
render() {
if (!this.selectedFeature) return null;
return (
<ul>
{
Object.entries(this.selectedFeature.attributes)
.map((key, val) => <li>{key}: {val}</li>)
}
</ul>
);
}
}
When a new feature is clicked, I want the child component to display it. Currently, I can't make that happen unless:
Is there a way to do this without the child listening for events?
Thanks in advance.
The name of the property in the child component is selectedFeature
but the parent component is passing its value as selected-feature
, which is interpreted as a HTML-attribute and not a Stencil property. Hence, the property will never change and the child won't re-render.
Change the line accordingly and it should work:
<child slot="content" selectedFeature={this.selectedFeature}></child>