Headless
Headless demo built with Expressive MVC - the complete source below runs as an editable sandbox when JavaScript is enabled.
App.tsx
import './App.css';
import Split from './common/Split';
import { Component } from '@expressive/react';
export default () => (
<div className="container">
<h1>Headless</h1>
<p>
A Component without <code>render()</code> draws nothing. Children pass
through its context provider, which makes placement in the tree the entire
feature: it owns a lifecycle and hosts the suspense and error boundaries
for everything below it.
</p>
<Scopes />
<small>Same Readout, same class, two scopes - each finds the Ticker above it.</small>
</div>
);
const Scopes = () => (
<Split>
<Ticker rate={100}>
<Readout />
</Ticker>
<Ticker rate={1000}>
<Readout />
</Ticker>
</Split>
);
class Ticker extends Component {
rate = 1000;
elapsed = 0;
get seconds() {
return (this.elapsed / 1000).toFixed(1);
}
mount() {
const started = Date.now();
const timer = setInterval(() => {
this.elapsed = Date.now() - started;
}, this.rate);
return () => clearInterval(timer);
}
}
const Readout = () => {
const { seconds, rate } = Ticker.get();
return (
<div className="readout">
<strong>{seconds}s</strong>
<small>every {rate}ms</small>
</div>
);
};
App.css
.readout {
display: flex;
flex-direction: column;
gap: var(--s1);
padding: var(--s4);
}
.readout strong {
font-family: var(--font-mono);
font-size: var(--t-2xl);
color: var(--accent);
}