Compose Render Props

April 9th, 2018 3 min read

No translations available.Add translation
💿 This blog post involves React, but was written before Remix was launched. Learn how Remix drastically simplifies React applications from the post:
Remix: The Yang to React's Yin ☯

Check this out:

The example itself is a little unimpressive from a user experience standpoint (it's based on someone else's actual use-case and I didn't have a chance to update it to look pretty). But the underlying code there is what I want to talk about.

When I created downshift, I gave it the following tagline:

🏎 Primitives to build simple, flexible, WAI-ARIA compliant enhanced input React components

The key word here is "Primitives." Initially I expected that people would build cool autocomplete/dropdown packages on top of downshift and publish those to npm. I was about to write: "I have been surprised that nobody's done this." But then I checked and it turns out several libraries are in fact providing an autocomplete solution with beautiful styling and nice defaults that give a more out-of-the-box feel for downshift. I only looked briefly, but I especially love the demos from mui-downshift and evergreen-ui. Very cool!

These libraries get the point of the render prop pattern. As I said in the tweet earlier. The real power of the render prop is in its ability to be used as a building block for building other components that have useful opinions. Downshift itself makes opinions about the logic of an enhanced selection input, and then these libraries jump on top to provide opinions about what that looks like visually to the user and provide a nice API for adapting those opinions to your use cases.

My next tweet (after the one lined above) was:

This week I livestreamed myself in the process of doing this for a component I'm working on. You can find the recording here. This component is a special amount input component that has a currency selection and the input has some special behaviors (like changing the font size the wider it gets etc.). The logic behind the component is what I'm trying to share. It will have three implementations for how it will look. For now, the layout of all three implementations is:


Though the layout is the same, the styles are different. Normally I'd account for those differences with CSS, but I'm confident that in the future it could have more layouts and styles. So I'm planning on having a few layers of abstraction to optimize for the flexibility (read: deletability) of the code. From top to bottom:

  • Component that handles styles
  • Component that handles layout
  • Component that handles logic

Doing things this way gives use a lot of flexibility. At first I'll have one component at the bottom layer, one component at the layout layer, and three components at the style layer. In the future, if we need another component that behaves the same way, but is laid out differently, we can implement a new layout and style component on top of the logic component and benefit from 90% of the work that went into this initial implementation.

And that in my mind is the real benefit of this pattern. Making clear separations of functionality that a component has which enhances the flexibility, deletability, and usability of this API.

I hope this is helpful! Good luck!

💿 Don't forget to checkout Remix: The Yang to React's Yin ☯
Kent C. Dodds
Written by Kent C. Dodds

Kent C. Dodds is a JavaScript software engineer and teacher. He's Co-Founder and Director of Developer Experience at Remix! Kent's taught hundreds of thousands of people how to make the world a better place with quality software development tools and practices. He lives with his wife and four kids in Utah.

Learn more about Kent

If you found this article helpful.

You will love these ones as well.