Async
Async demo built with Expressive MVC - the complete source below runs as an editable sandbox when JavaScript is enabled.
App.tsx
import './App.css';
import { Control } from './Control';
const App = () => {
// Control is a State, separating concerns of this component.
// This focuses on presentation, while Control focuses on behavior.
const { agent, dead, getNewAgent, remaining } = Control.use();
if (dead === true)
return (
<div className="container">
<div className="emoji">🙀💥</div>
<h2>Unfortunately, the cat exploded.</h2>
</div>
);
if (dead === false)
return (
<div className="container">
<div className="emoji">😸👍</div>
<h2>Oh, the cat did not explode.</h2>
</div>
);
return (
<div className="container">
<h1>Async Example</h1>
<div className="timer">
<h1 className="box">📦</h1>
<p>
<b>Agent {agent}</b>, we need you to defuse the bomb!
</p>
<p>
If you can't do it in <span className='seconds'>{remaining}</span> seconds, Schrödinger's cat may or
may not die. But there's still time!
</p>
<p>
<button onClick={getNewAgent}>Tap another agent</button>
if you think they can do it.
</p>
</div>
</div>
);
};
export default App;
App.css
.timer {
display: flex;
flex-direction: column;
align-items: center;
max-width: 400px;
gap: var(--s3);
}
.seconds {
width: 1.2em;
display: inline-block;
}
.timer p {
margin: 0;
}
.timer button {
margin: 0 var(--s2);
}
.box {
margin: 0;
font-size: 4rem;
line-height: 1;
}
.emoji {
font-size: 2rem;
line-height: 1;
}
Control.tsx
import State from '@expressive/react';
export class Control extends State {
// Properties set starting values; assignments dispatch updates.
agent = 'Bond';
remaining = 30;
dead?: boolean = undefined;
// new() runs once when ready. The returned function runs on
// teardown - handy for clearing timers or subscriptions.
protected new() {
const timer = setInterval(() => {
if (--this.remaining > 0) return;
this.dead = Math.random() > 0.5;
clearInterval(timer);
}, 1000);
return () => clearInterval(timer);
}
// Async methods assign to `this` - no thunks needed.
async getNewAgent() {
const res = await fetch('https://randomuser.me/api?nat=gb&results=1');
const data = await res.json();
this.agent = data.results[0].name.last;
}
}