Async Generators as an alternative to State Management

Vitaliy Akimov
Jun 14, 2018 · 10 min read
Image for post
Image for post

TL;DR

  • With Async Generators there is no longer need for components state, state management tools, component lifecycle methods, and even the latest React Context and Suspense APIs. It is much simpler to develop, maintain, and test.
  • Unlike a state management approach, async generators tame asynchronicity leaving mutations harmless (if visible only in the generator’s scope).
  • This approach has a functional programming background too.
  • State persistence for things like time traveling, universal apps is also available.
  • The article uses React and JavaScript, but the technique is applicable in any other framework or programming language with generators (coroutines).
  • I’m advertising my tool only at the end and very briefly. Most of the article is about async generators without any dependency.
Image for post
Image for post
Image for post
Image for post

Turning components inside-out

Generator functions are functions returning iterators. We can do with them everything we can do with plain functions. For example, by composing generator functions, we can split computation into a few independent stages. Each stage has own encapsulated state. Each stage receives messages which were yielded on the previous stage, handles them yielding another messaging and passing them to the next stage.

Extension

An exciting point of this technique is nothing should be preliminary designed to make the program reusable and decoupled. Nowadays premature abstraction is probably a bigger evil than premature optimization. It almost definitely leads to an overdesigned mess impossible to use. Using abstract generators, it is easy to keep calm and implement the required features, splitting when needed, without thinking about future extensions, easy to refactor or abstract some common parts after more details are available.

Performance

Async generators overhead is much smaller than for state management libraries. But there are a lot of ways to get performance problems here too, e.g. over flooding with messages. But there are also a lot of almost effortless ways to improve performance.

Testing

Comparing to Redux reducer tests, generators fit a bit darker box testing strategy. The tests don’t have access to the current state. Though still, they are very simple to write. With Jest snapshots, the test can be a list of input messages with comparing output using snapshots.

Persistent state

There is another motivation for Redux described in You Might Not Need Redux article by Dan Abramov — namely providing access to the state and it can be serialized, cloned, diffed, patched, etc. This can be used for time travel, hot reloading, universal applications and more.

const backend = pipe(
commonTask1,
memo(pipe(
renderTask1
renderTask2)),
commonTask2)
yield {type:”LAZY_CONTROL”}
yield {type:”CONTROL”, value: await import(“./lazy_component”)}

Functional Programming

Commonly used state management tools have FP background. The code from the article doesn’t look like FP in JavaScript because of imperative for-of/switch/breakstatements. It has a corresponding concept in FP too. It is so called Monads do-notation. For example one of their use in Haskell is to resolve problems like React components property drilling.

Effectful.js

Effectful.js is a babel preset implementing do-notation working for any monad without any JavaScript syntax extension. It also supports state persistence with a reference implementation in es-persist library. For example, this may be used to convert all async generators example above into pure functions.

Image for post
Image for post

DailyJS

JavaScript news and opinion.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store