Write reusable sane API-based Contentful components using the Render Props pattern

Published on January 23, 2018

RenderPropsPAttern

I play around with JavaScript SDKs a lot. And most of my projects make use of Contentful to pull in content from editors and non-technical people into my applications.

It doesn't matter if I'm dealing with edited content or GitHub statistics, almost every dataset is available to me via API endpoints. Those datasets then go into my React, Preact or Vue.js applications. Up until today I hadn't figured out the best way to work with API data in a component-driven world. But you know what — now I know.

Common implementations of API calls

Whether you use the widely supported fetch method or an SDK, using API data across tons of components can be tricky. This is because you have to figure out in which component you fetch the data, how you handle state and how to propagate data across components.

Consider the following Preact snippet:

In this code, the App component fetches the data in the lifecycle method componentDidMount. It then sets the response data to the given state of the component which will in turn be used in its render method.

But what happens if I have to make two calls to fetch data?

You can play with this example on CodeSandbox if you like.

Now I have to make two calls using the getEntries Contentful SDK client – both included in componentDidMount. But to me this code feels a bit messy. And it will get worse the more calls you have to make.

In the past, this situation would force me to restructure some code and abstract the API calls away — and maybe use a state management library like Redux or Vuex to keep the components clean.

The downside of abstracting things into models or utils is that it increases the component complexity. As a result, it might not be obvious what's going on for a developer joining the project. I have to jump between files to understand functionality, and components have to include an increasing number of features.

On the other hand, using state management with something like Redux comes at a cost. So using state management should be very well considered since it might add unwanted complexity.

The desired way of making API calls

I've always dreamt of a magical component that abstracts everything away and provides me with data in a particular "scope." In Vue.js when you loop over items, there are objects magically available inside of directives:

As seen above, every item is available inside of the looping li element. Can this approach be used for handling API calls?

I planned to dig into the Vue.js core to figure out if that's possible, but then...

Meet the "render props" pattern

I was listening to an episode of Fullstack Radio with Kent C. Dodds as the guest. The title was "Building Reusable React Components with Render Props." Interesting - I'm listening!

This immediately caught my attention. Kent talked about the downshift react component, which is a reusable autocompletion component. It can be used to build, well... custom autocompletion components.

The catch is that it provides functionality like keypress handling and item selection — and as a user I only have to deal with providing the interface. I only have to define the markup structure and "make it pretty" so to say.

The way it works is by making heavy use of the so-called "render props" pattern to provide its functionality. Kent explained how it works - it matched my expectations of a beautiful reusable component structure that makes it possible to share functionality without increased complexity.

The idea of the "render props"

The "render props" pattern works like so:

I use a provided component and pass in a render function via props. This render function will then be called inside of the render method of the provided component. Possible logic and API calls can be done in the "wrapper component", and data can be passed to the function I handed in.

Using the "render props" pattern in React

Just because downshift is written in React, let's have a look at how the "render props" pattern could work for making API calls in React.

Using a prop named render

First I have to write the "render props" component to fetch data from a Contentful API endpoint.

The snippet above looks like a lot of code for just making an API call — but now I have "component superpowers". So how can I clean up this API call?

You can play with this example on CodeSandbox.

It might seem funny to pass an anonymous function as a prop, but when you look at it, this looks very close to what I had imagined making API calls – a component wrapper that hides the call and lets me define the visual presentation.

The anonymous function is executed with an object including items that are part of the API response. Pretty sweet!

Using the children prop

I understand that this pattern might make some people uncomfortable, because writing JSX inside of a prop might seem weird. Thankfully there is an even more beautiful way to do it. The React docs describe "render props" as:

It’s important to remember that just because the pattern is called “render props” you don’t have to use a prop named render to use this pattern. In fact, any prop that is a function that a component uses to know what to render is technically a “render prop.”

It turns out that when you place a function inside of a component, this function is also available as props.children. Remember the following lines?

I can modify it to make use of the children prop.

And now it becomes even more magical! 🎉

You can play with this example on CodeSandbox if you like.

If I put one function inside(!) of the component it will be available via this.props.children of the wrapper component.

Quick side note: If you place several functions inside of a component children will become an Array.

The code above now looks like 95% of what I dreamed of!
(That's something I can live with.)

Using the render prop pattern in Preact

I started this article with talking about Preact – is this pattern also usable in other frameworks than React?

Yes it is! When using this pattern in Preact, there is only one tiny difference. Preact does not provide the convenience functionality of children being a function when there is only one child available. That means that props.children is always an Array. But hey... this is a no-brainer.

You can play with this example on CodeSandbox if you like.

The rest stays the same. Pretty neat!

Using the render prop pattern in Vue.js?

By now I have covered React and Preact. So what about my darling Vue.js? Vue.js is a little bit special. You can use JSX in Vue.js, but yeah... everybody I know writes single file components and mixing template elements with JSX render functions doesn't feel right to me. Darren Jennings clearly describes how you can make it work with mixing these two ways of writing Vue.js components in this article.

Scoped slots in Vue.js

If you write a lot of Vue.js code, you might wonder if you could transfer the idea of handing in a template that gets data passed to it into a component using slots. And you're right! It turns out since Vue.js v2.1 there is the possibility to use scoped slots that make it possible to pass data into the content you want to put into slots.

This principle is hard to explain without code, so let's have a look.

This Contentful component defines a named slot called render, and then passes the given data into it – items in this case. The other functionality is more or less the same as in the Preact and React examples. The component includes validations for props and makes the actual API call.

The exciting part is the following:

You can play with this example on CodeSandbox if you like.

I can now define the query on the Contentful component and use the named slots to pass my template into the component. To retrieve the API data I can use the slot-scope attribute (supported since Vue.js v2.1) and make items available inside of my passed in template.

This way I don't have to deal with the JavaScript SDK client at all! Because of its verbosity, it doesn't look as lovely as the "render props" pattern in React/Preact, but the outcome is the same – a reusable API component. 🎉

API calls should be components

After building single page apps for more than five years now, I have to say that these patterns convinced me. It finally feels easy to make calls in simple apps following a component mindset. Hide the functionality in a component and allow me to make it pretty! I like that.

And please don't get me wrong, proper abstractions are needed when you have significant complexity, and Redux and co. are great tools to deal with large apps full of functionality. But when it's just me fetching some data in a simple app, this is the way to go for me now.

Additional resources

If you're not convinced yet that "render props" are the way to go react-router maintainer Michael Jackson gave a fantastic talk on this topic comparing mixins, higher order components and the "render props" pattern. Make sure to check this one out!

Try Contentful components

Contentful is content infrastructure for any digital project. Sign up now for free to give it a spin!

Subscribe for updates

Build better digital experiences with Contentful updates direct to your inbox.

Stefan Judis

Stefan Judis

Senior Manager of Developer Relations

Stefan loves web performance, new technologies, and accessibility. He is also a curator of the online resource [Tiny Helpers](https://tiny-helpers.dev/ "Tiny Helpers"), contributes to a variety of [open source projects](https://github.com/stefanjudis "open source projects"), and enjoys [sharing nerdy discoveries](https://www.stefanjudis.com/today-i-learned/ "Today I Learned").

Related articles

React memo is a higher-order component that boosts performance by memoizing functional components. Learn how and when to apply it for optimized re-renders.
Guides

What is React memo? How to improve React performance

November 8, 2024

Contentful launches two more hands-on courses for developers.
Guides

Contentful launches two more hands-on courses for developers

August 2, 2022

An enterprise CMS is a content management system that meets the needs of enterprise-class companies. Read on and decide if your organization needs one.
Guides

What is an enterprise CMS?

January 19, 2024

Contentful Logo 2.5 Dark

Ready to start building?

Put everything you learned into action. Create and publish your content with Contentful — no credit card required.

Get started