Slaying a UI Antipattern in React

Solving a well known a UI problem with React

A. Sharif
A. Sharif
Nov 4, 2017 · 3 min read

The following write-up is based on Stefan Oestreichers blog post Slaying a UI Antipattern in Fantasyland which was originally influenced by Kris Jenkins excellent how Elm slays a UI antipattern.

Just a quick overview of the anti-pattern we’re talking about here. Typically you might see data represented like the following i.e.:

const data = {loading: false, errors: null, items: []}

Here’s how this is described by Stefan Oestreicher:

But of course it’s easy to forget to check the loading flag or maybe you just can’t be bothered right now because of time constraints and “will do it later”. It also just makes for awkward code everywhere. Setting the items to null instead of an empty array creates even more problems so that won’t help either.

Stefan Oestreicher, Slaying a UI Antipattern in Fantasyland

So we have to manually keep track of the current data status, making sure we don’t forget to set the correct loading, error and data state. It’s very easy to forget to set the loading to true to false, if you think about it. Forgetting to keep the state in sync leads to a false representation in the UI.

In Slaying a UI Antipattern in Fantasyland we are represented with a different way to think about the problem:

type RemoteData e a
= NotAsked
| Loading
| Failure e
| Success a

We might have different states to represent in the UI, i.e. NotAsked (we haven’t done anything yet). By modelling all possible states, we can resort to using daggy f.e., which enables us to handle the possible outcomes.

const RemoteData = daggy.taggedSum({
NotAsked: [],
Loading: [],
Failure: ['error'],
Success: ['items'],
})
// in our constructor
this.state = { items: RemoteData.NotAsked }

(* Taken from Slaying a UI Antipattern in Fantasyland)

By now we should have good low level idea on how to solve this anti-pattern.

<Loader />

What if we could take all these ideas and wrap them inside a React component, which takes care of all of this, without having to manually take care of the low level stuff.

Michael Jackson wrote about the render-props concept in his Use a Render Prop! post. In short:

A render prop is a function prop that a component uses to know what to render.

More generally speaking, the idea is this: instead of “mixing in” or decorating a component to share behavior, .

Michael Jackson, Use a Render Prop!

So we can pass in a function via a defined prop and access any needed values to render the needed outcome. Now, what if we could leverage this concept and define multiple props?

What if we could define a render prop for every possible state for our previously defined remoteData structure? Let’s see how we can approach this concept with a high level example.

So we defined a specific render prop of every possible outcome. Now we don’t have to think about if the UI is representing the proper state, all we need to do is tell what we want to see if the component is loading, has an error and has any data.

Now that we have an idea of how Loader should work, let’s implement the functionality.

As we can see, we don’t need too much to have a full functioning Loader component, that can be configured via render props.

If there are better ways to solve these problems or you have any questions, please leave a comment here or on .

JavaScript Inside

All things JavaScript.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

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