Learning Higher-Order Components in React by Building a Loading Screen

Let me share a secret: no matter how long you’ve been doing something, you’re bound to have to relearn some part of it. I haven’t built my own higher-order component in a long time and made a lot of mistakes. Real mistakes.


The other day I was adding a simple loading indicator to screens in my new app. You’ve probably used this pattern before:

This is great. It’s simple and convenient for one screen. If you’re not used to React Native, ActivityIndicator is one of the beautiful parts of app development — a component that exists.

When you find yourself repeating this same pattern often, its nice to see what we can do to rid ourselves from the tedious task of Copy & Paste.

What do I know?

I know that I’ll have a loading prop FOR SURE.

What am I apprehensive about? The strategy I will use to genuinely make my life easier (instead of harder — sometimes we need a friendly reminder).

First Pass

Besides the function wrapping React.PureComponent everything should look familiar. If you want to skip ahead and use this as-is, just paste this into our InfoScreen file and wrap the export:

export default withLoadingScreen(InfoScreen)

This pattern may look familiar if you’ve used Apollo or Redux before:

export default connect(mapStateToProps, mapActionCreators)(InfoScreen)


If you’re wondering how to use both connect and withLoadingScreen you can wrap the components individually or use a compose function. Writing a compose function by hand is cool, but importing the one from one of the libraries you’re already using is cooler. Both redux and react-apollo come bundled with their own:

Does it work?

Depending on what your setup looks like, it might work perfectly or it might not work at all! 😃 🙃

I’m using react-navigation which supports a static method called navigationOptions to override header title and styles.

The loading screen works as intended, but the header styles are gone! What happened? Static methods aren’t copied over! It’s super easy to overlook but also super easy to fix.

There’s a library called hoist-non-react-statics that will automatically copy over static variables like navigationOptions , defaultPropsand propTypes.

Second Pass: Hoisting Static Variables

Instead of returning the class immediately, we return it only after calling hoistNonReactStatics . The header is rendering correctly again. Woo!

Third Pass: Passing in Options

Now that the loading screen itself functions correctly, I want to pass in a different loading indicator size for different screens.

Sometimes the default loading indicator is too big or the wrong color so I’d like to be able to adjust when I need to.

connect and graphql both give you options:

connect(mapStateToProps, mapActionCreators)

graphql(MyQuery, { options })

We can do the same by adding another function call:

In this case I wanted to control the size of the ActivityIndicator

withLoadingScreen('large')(InfoScreen)// or using compose:compose(
compose(mapStateToProps, mapActionCreators)

Bonus Round: Naming Your Components

You’re bound to run into issues. Sometimes the component name doesn’t show up or doesn’t match the component in question. We can fix this easily by writing a simple function called getDisplayName :

function getDisplayName(WrappedComponent) {
return (
WrappedComponent.displayName || WrappedComponent.name || "LoadingScreen"


Higher-order components have a few weird things about them that you can fix easily. Code responsibly.

Fun things to do:



Just a millennial looking for a feature-free rewrite.

Love podcasts or audiobooks? Learn on the go with our new app.

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