Effect Helper
When using state data you notice that only the part of the template dependent on the state will update with changes.
For those situations you could want to perform "side effects", meaning, you want other part of the template to change with the state change.
That is when the effect
helper comes in. To help
you perform these side effects directly in the template.
const doubleCount = () => count() * 2;
const counter = html`
<p>${count}</p>
<!-- Also display count doubled whenever count changes -->
<p>${effect(count, doubleCount)}</p>
`;
Above example shows a simple example of how to perform a side effect to display double of count whenever count changes.
Bellow example shows that using effect
we can react
to something like the activeTab
state change to
dynamically get content for the tab and render it.
type Tab = 'home' | 'about' | 'contact';
const tabContent: Record<Tab, HTMLTemplate> = {
home: html`<h1>Welcome</h1>`,
contact: html`<p>Tell us what you think</p>`,
about: html`<p>We are here to help you</p>`,
}
const [activeTab, setActiveTab] = state<Tab>("home");
const app = html`
<h1>Tab Example</h1>
<ul>
<li
class.active="${is(activeTab, 'home')}"
onclick="${() => setActiveTab('home')}">
Home
</li>
<li
class.active="${is(activeTab, 'about')}"
onclick="${() => setActiveTab('about')}">
About
</li>
<li
class.active="${is(activeTab, 'contact')}"
onclick="${() => setActiveTab('contact')}">
Contact
</li>
</ul>
${effect(activeTab, () => tabContent[activeTab()])}
`;
app.render(document.body)
Effect format
The effect
helper takes comma-separated states and
the last argument must be the action to take or, the "thing" you
need to be returned or rendered.
effect(STATE, ...STATE, SIDE_EFFECT_ACTION)
// react to 'activeTab' and 'currentPath' state changes
// to load content by calling 'contentLoader'
effect(activeTab, currentPath, contentLoader)