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.
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
But what happens if I have to make two calls to fetch data?
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.
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...
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 "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.
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.
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?
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!
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
And now it becomes even more magical! 🎉
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.)
renderprop 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.
The rest stays the same. Pretty neat!
renderprop 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.
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:
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.
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.
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!
Contentful is content infrastructure for any digital project. Sign up now for free to give it a spin!