Similar ideas to Concur UI lib #17
Replies: 2 comments 2 replies
|
I didn't realize you ported Concur to JavaScript! Did you notice anything specific the two libraries could learn from each other? |
|
Concur-js is more of a proof of concept right now, the API and performance could certainly be better. Crank is probably more pragmatic for JS development and does things in a more JS idiomatic way. However, Concur's semantic model is very well developed and brings a bit more of a disciplined approach, which I think scales better in the long run. For example, Concur components have return values and can be combined with generic combinators. I took the time to convert the example from crank's README. Compare Concur's solution below which has reusable combinators combined with minimal app-specific code, with the much more stateful code using Crank - First we can define a generic combinator which throttles the output of a widget. This could go in a library of some kind. function throttle(timeout, widget) {
var isThrottled = false;
var timer = null;
var reset = () => {
isThrottled = false
timer = null
}
return async function*() {
var res = yield* widget()
while(isThrottled) {
res = yield* widget();
}
isThrottled = true
if(!timer) timer = setTimeout(reset, timeout);
return res;
}
}If we wrap this around a button with a timeout 2000, the button's click will only work after a 2 second timeout. const throttledButton = throttle(2000, async function* () {
yield* <button onClick>Show me another dog</button>
})We can create another generic component which can show a loading indicator for any type of async action. This could also go in a library - function loader(axn, msg) {
return <div>{axn()}<div>{msg}</div></div>
}And wrap it around our Dog data loader. This component will fire off an ajax request, show a loading indicator and then show the dog image when complete - async function* RandomDog() {
// Get data
var data = yield* loader(async function*() {
var res = await fetch("https://dog.ceo/api/breeds/image/random")
return await res.json()
}, "Fetching a good boy...")
// Display picture
yield* displayView(
<a href={data.message}>
<img src={data.message} alt="A Random Dog" width="300" />
</a>)
}Finally, we want to compose a throttled button, and the random dog generator together. forever(() =>
<div>
{throttledButton()}
{RandomDog()}
</div>) |
Uh oh!
There was an error while loading. Please reload this page.
Hi, you might be interested in checking out my Concur UI library which takes these ideas to their logical extreme!
It was originally written for Haskell (https://github.com/ajnsit/concur), then Purescript (https://github.com/ajnsit/purescript-concur), and even Javascript (https://github.com/ajnsit/concur-js). But the Javascript port is more of a proof of concept. Perhaps we can figure out a way to collaborate on the JS version?
There is some documentation here - https://github.com/ajnsit/concur-documentation/blob/master/README.md
All reactions