How to Get Your Teen to Agree with You

What does family time mean for you and your family? Which aspects come easy and naturally? Which aspects are challenges or struggles? Perhaps undesirable behaviors or unmet expectations come to mind…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




UI as an afterthought

Or: how will React context and hooks change the game of state management?

A question people ask me regularly: “How do all the new React features (context, hooks, suspense) affect how we build (web) apps in the future? Do they make state management libraries like Redux or MobX obsolete?”

With this post, I’ll try to answer that question once and for all! To truly understand the question, we’ll need to do a little groundwork. Let’s step back, and leave React, Redux and MobX alone while we answer a more fundamental question.

What is a web application? For the purpose of this post: A web application is a user interface that allows customers to interact with your business. The key take-away here is that it is a user interface. Not the. The goal of a nice front-end: provide a nice, friction-less experience to your customers to interact with your business processes. But the front-end is not the business itself!

I notice that in front-end development we often approach user interfaces from the opposite angle: We start from some mock-ups and then add pieces of state at almost arbitrarily places to make the whole thing come alive. Basically, state and data is an afterthought, a necessary evil that is needed to make that beautiful UI work. Working your application from that side inevitably leads to the conclusion: State is the root of all evil. It’s that horrible thing that makes everything that was beautiful at first, ugly and complicated. But here is a counter-thought:

Information. The opportunity for customers to interact with business processes are ultimately the only thing that make money. Yes, a better UI experience will most likely lead to more money. But it is not the money generator itself.

So, in my humble opinion, we should approach building web apps from the opposite direction, and first encode what interactions our customers will have with our systems. What are the processes. What is the information he will need? What is the information he will send? In other words, let’s start with modelling our problem domain.

The solutions to these problems are things we can code without reaching for a UI library. We can program the interactions in abstract terms. Unit test them. Build a deep understanding of what different states all these processes can be in.

At this point, it doesn’t matter yet what the nature of the tool is that the customers use to interact with your business. A web app? A React native application? An SDK as NPM module? A CLI? It doesn’t matter! So:

Now you might be wondering: “Aren’t you horrible over-engineering? Why should I build my app as if I am about to release a CLI? I am clearly never going to do that…. Are you unicorn-puking me?”

Now, stop reading this blog for a moment and go back to the project you are currently procrastinating on, and fire up your test runner…. Now tell me again: Does your app have a CLI or not? Every dev on your team has a CLI (hopefully): the test runner. It interacts with and verifies your business processes. The fewer levels of indirection that your unit tests need to interact with your processes, the better. Unit tests are the second UI to your system. Or even the first if you apply TDD.

React does a really awesome job to allow unit tests to understand a component UI and interact with it (without having a browser and such). But still, you should be able to test without the indirections introduced by concepts such “mounting”, “rendering” (shallow or not?), “firing events”, “snapshotting UI”. These are all concepts that don’t matter for the business domain, and unnecessarily bind your logic to React.

So, at this point you might have some clue why I always have been an opponent of directly capturing domain state in React component state. It makes the decoupling of business processes and UI unnecessarily complicated.

Only when you have captured the customer processes, tested, and verified them, it starts to matter what the actual UI should look like. What technology it is built with. You will find yourself in a very comfortable position: As you begin building components, you will find that they don’t need that much state. Some components will have some state of their own, as not all UI state is relevant for your business processes (all volatile state like current selection, tabs, routing, etc). But,

You will also discover that testing becomes simpler; you will write way less tests that mount components, fire events etc. You still want some, to verify that you wired everything correctly, but there is no need to test all possible combinations.

The great decoupling allows very rapid UI iteration, A/B testing, etc. Because once the domain state and UI have been decoupled, you are much more free to restructure your UI. Heck, even switch to a completely different UI lib or paradigm becomes cheaper. Because state is largely unaffected by it. Which is great, as in most applications I’ve seen the UI develops in much higher pace than the actual business logic.

For example, at Mendix we used the above model with great success. This separation has become the paradigm everyone naturally follows. An example: The user needs to upload an excel sheet, next we run some client side validations on it, then we interact with the server, and finally we kick off some processes. Such a new feature would first result in a new store (just a plain JS class) that captures the internal state and methods for every step of the process. It would capture the logic for verification. The interactions with the back-end. And we would create unit tests to verify that the right validations messages are generated and that the whole the process works correctly under all it’s state permutations and error conditions. Only after that point, people start building the UI. Pick a nice upload component, build forms for all the steps. And maybe change the original validation messages if they don’t sound right.

At this point you might also understand why I am not a fan of the things that mix back-end interaction directly into the UI. Such as the react-apollo bindings as means to interact with graphQL. Back-end interaction like submitting mutations or fetching data is the responsibility of my domain stores. Not the UI layer. React-Apollo so far feels to me as a shortcut that too easily leads to a tightly coupled setup.

Finally! It is time to go back to our original question: “How do all the new react features (context, hooks, suspense) affect how we build (web) apps in the future? Do they make state management libraries like Redux or MobX obsolete?”.

The answer for me is: The new features don’t change the game of state management. The context and hooks features don’t enable React to do new tricks. These are just the same tricks, significantly better organized, more composable and in a less error prone way (clearly, I’m a fan!). But React, out of the box, can only respond to state that is owned by components. If you want your domain state to live outside your component tree, you will need a separate state management pattern, abstraction, architecture, library, to organize that.

In other words: if you just figured you don’t need Redux or MobX anymore since the introduction of Context and hooks: Then you didn’t need those before either.

Talking about suspense versus state management in general: I think it just proves the sanity of the separation of concerns: Suspense + React state is great to manage all the UI state, so that there can be concurrent rendering and such. Supporting concurrency makes a lot of sense for volatile state like UI state. But for my business processes? Business processes should be exactly in one state only at all times.

So, with that, we hopefully answered the question about modern React versus state management:

Before we part, let’s go meta: every blogger knows that a blog needs images to engage users. This blog didn’t feature any images yet and hence has a poor, sub-optimal UI. But still can perform all it’s “business goals”: Sharing the above thoughts with you. Because, although extremely crucial, from an implementation perspective:

Once business processes are captured in stores, you can use them to drive your UI as well!

Add a comment

Related posts:

What did I develop from my tooth fairy?

I accept everything she says in a positive way and challenge.

Interfaces de telas web

Interfaces de telas web. Páginas criadas com Wordpress + Elementor para uma startup.

The Colonial Grip

This was originally published on 14 September 2020. I’m just republishing it here because I’ve shifted my website! I’ve been listening to the audiobook of J.G. Farrell’s The Singapore Grip, a book…