Seamless State Management using Async Iterators

seamless-state-management-using-async-iterators

In my recent post about AI-UI, I touched on why I developed the library.

  • I wanted declarative markup
  • I wanted type-safe component encapsulation, with composition & inheritance
  • I wanted a small, fast client-side solution with no complex build process (or any build process!)

…but most importantly…

  • I didn’t want to learn a whole new API just to manipulate data I already have in my app

In my single page apps, I’ve got remote APIs and endpoints that supply data. Sure, I might want to do a bit of arithmetic, sorting, formatting, but basically, I want to say to the UI: “Here’s my data, render it into the DOM”. When the data changes, either because the server tells me or the user manipulates it locally, I don’t want to re-render anything – I’ve already laid out my page – I just want the DOM automagically re-render.

How can I do this using the most familiar JS syntax possible? Iterable Properties

Show me!

Let start with one of the basic examples in the AI-UI repo: a clock.

We’re not really interested in the clock itself, we’re going to use Chrome Dev tools create iterable properties on a basic JS object, and see how they work. Go to the example, and open Dev Tools with Ctrl (Cmd) + Shift + I

Create an object

We’re using this script (as opposed to the ECMA module) as it defines the global constant AIUI, so we can just play.

A key sub-module of AIUI is the Iterators interface. Let grab a reference to it for later use, and just create a plain old JS object.

In the Dev Tools console, type:

defineIterableProperty = AIUI.Iterators.defineIterableProperty;
xxx = { foo: 123 };

So xxx is just an object. Nothing special here. Let’s add an iterable property to it. The syntax is defineIterableProperty(object, key, initialValue):

defineIterableProperty(xxx,"bar",456);
// xxx.bar just looks like a normal property:
xxx.bar * 10
// 4560
xxx.bar -= 111;
// 345

Add an iterable property and use as normal

But xxx.bar has some magic: it’s also an async iterator

for await(const v of xxx.bar) console.log("bar is now",v)
// bar is now 345
xxx.bar = 100
// bar is now 100
//100
xxx.bar++
// bar is now 101
// 100
xxx.bar = "Wow!"
// bar is now Wow!
//'Wow!'

If you prefer a more functional style, AI-UI comes with a handy bunch of helpers like map, filter and consume

xxx.bar.map(v => v * 10).consume(v => console.log("Or 10x more is",v));
// Promise {}  
xxx.bar = 99;
// bar is now 99          <--- for...await is still going!
// Or 10x more is 990     <--- same value mapped
// 99

Watch it change

Is that it?

Yep. That’s it. No ‘setState()’, no hooks, signals, or other API to learn. You just define an iterable property, read and write to it like normal, and consume the results as it changes.

It’s this simplicity that makes AI-UI one of the simplest UI modules to use. Just layout your markup specifying iterable values in your variable substitutions like

${xxx.bar}

, and it just works by consuming your iterable values and updating the DOM.

Of course, defining all your own properties by hand is a bit repetitive, so AI-UI components can create a bunch for you using the iterable member, but that’s not the core functionality.

The Iterators submodule is pure-JS, with no DOM dependencies, so you can use it in NodeJS apps with

import '@matatbread/ai-ui/esm/iterators.js';

Start iterating now!

Total
0
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Post
why-did-you-build-that-feature? 

Why did you build that feature? 

Next Post
evolve-additive-solutions-announces-new-ceo,-jeff-blank

Evolve Additive Solutions Announces New CEO, Jeff Blank

Related Posts