Loading State Trick for Stateless Functional Components in React

I want to share with you a little trick I’ve been using lately with stateless functional components in React. This is probably really old news to some of you, but I’m hoping there are a few of you who don’t know this one yet.

If you’re getting started with React, and especially if you’re using Redux, you’ve probably come across the concept of container and presentational components.

Container components provide data to nested components. These components will generally use lifecycle methods, such as componentDidMount, to fetch some data and pass it down.

Presentational components, on the other hand, are used solely for displaying data passed into them and generally do not use any lifecycle methods. Often, if a presentational component does not require any lifecycle method (other than the required render), then this component is written as a stateless functional component.

A stateless functional component is simply a function that returns the markup (React functions or JSX). Props are passed as arguments to the function, and then utilized within the markup. Let’s make a simple example of a stateless functional component that expects an array of items, and displays each one of those items.

import React, { PropTypes } from 'react'

const DisplayItems = ({ items }) => (
  <div className='items'>
    { items.map((item, index) => <div className='item' key={index} {...item} />) }
  </div>
)

Display.propTypes = {
  items: PropTypes.array
}

export default DisplayItems

I hope the ES6 doesn’t scare you. I’ve created a function called DisplayItems. This function expects a props object as an argument, and I’m using ES6 destructuring to make it clear that I’m expecting and will use an items property on the props object.

Then, I am using the implicit return feature of ES6 arrow functions to return the markup (in this case JSX, it’s all I really use) from within the body of the function.

Then, I map over each item, returning another div. React requires that we add a key attribute to items that are dynamically populated, which is often the case with displaying arrays. In this case, it was easy to use the index, but it might be more useful to use a property on the item itself in your case.

Lastly, I am using ES6’s Object spread syntax to pass all props from item into the div. In your example, it is possible that this inner item div would be another presentational component that needs access to all the props on item.

Thus, if we used this in our app, regardless of how many items we pass to this stateless functional component, React would give us the wrapping div, and then any divs generated by the map function.

But what if you currently don’t have any items and you don’t want to display the wrapping div until you have items?

It is possible to reconfigure this component to display alternative markup if there are no items to display.

Imagine that I have built another component called LoadingSpinner which simply shows the user a loading spinner animation. Perhaps it looks something like this:

import React, { PropTypes } from 'react'

const LoadingSpinner = () => (
  <div className='loading_spinner-wrap'>
    <svg className='loading_spinner' width='60' height='20' viewBox='0 0 60 20' xmlns='http://www.w3.org/2000/svg'>
      <circle cx='7' cy='15' r='4' />
      <circle cx='30' cy='15' r='4' />
      <circle cx='53' cy='15' r='4' />
    </svg>
  </div>
)

export default LoadingSpinner

And maybe I’ve written some basic styles for it to animate the circles:

.loading_spinner-wrap {
  width: 100%;
  padding: 50px 0;
}

.loading_spinner {
  display: block;
  margin: 0 auto;
  fill: #000;

  circle {
    animation-name: upAndDown;
    animation-duration: 2s;
    animation-timing-function: cubic-bezier(.05, .2, .35, 1);
    animation-iteration-count: infinite;

    &:nth-child(2) {
      animation-delay: .18s;
    }

    &:nth-child(3) {
      animation-delay: .36s;
    }
  }
}

@keyframes upAndDown {
  0% { opacity: 0; transform: translateY(0); }
  25% { opacity: 1; transform: translateY(-10px); }
  75% { opacity: 1; transform: translateY(-10px); }
  100% { opacity: 0; transform: translateY(0); }
}

Now, I can set up my DisplayList component to either render the LoadingSpinner component, or my list, depending on whether any items have been passed to it. Like so:

import React, { PropTypes } from 'react'
import LoadingSpinner from './LoadingSpinner'

const DisplayItems = ({ items }) => {
  return items.length ? (
    <div className='items'>
      { items.map((item, index) => <div className='item' key={index} {...item} />) }
    </div>
  ) : <LoadingSpinner />
}

Display.propTypes = {
  items: PropTypes.array
}

export default DisplayItems

Did you see what I did there? I removed the implicit return from the DisplayItems function, and then used a ternary operator to determine which component gets rendered.

If items has any length other than 0, the ternary will evaluate to true and thus render our items list. However, if the length of the array is 0, it will evaluate to false and render our LoadingSpinner component. You might end up with something similar to this:

Loading Stateless Functional Component Gif

You could, of course, use any other component that you would prefer to render instead. You can determine what’s best for your project, and even what’s best per component. But if you’re looking for a way to indicate to your users that you’re expecting data to eventually make it to your stateless functional component, perhaps this pattern will be useful to you.

Let me know if this is helpful to you in the comments and link to any examples you have of this trick or similar ones. I’d love to see them.

  • Hi Kyle! First of all, thanks for writing this post 🙂

    I think is approach is more than valid and I actually use it often in projects for work. But somehow I don’t know why there is an inclination on developers to avoid states at all cost, like they were a bad thing (not saying is your case), when they are actually a good indicator to know if the component should update.

    I personally prefer a stateful component fetching the data, gathering both loading and stateless component and controlling the view, to say so.

    import { PropTypes, Component } from 'react'
    import LoadingSpinner from './LoadingSpinner'
    import DisplayItems from './DisplayItems'

    export default class DisplayView extends Component {
    constructor(props) {
    super(props);

    this.state = {
    data: null
    };
    }

    componentDidMount() {
    window.fetch('/some/data.json')
    .then(result => result.json())
    .then(data => this.setState({ data }));
    }

    render() {
    return (this.state.data === null) ?
    :

    }
    }

    Of course both approaches will work, the difference might be separation of concerns, I prefer DisplayItems to take care of actually displaying the items or even dealing with a probable empty array showing a no items result message and not the fetching in progress.

    Not only that, but you can use shouldComponentUpdate on the DisplayView component to have more control around render updates on its children.

  • Also, sorry if the code does not look good but f*****g Discuss highlighting sucks 🙂

    • Hey Jeremias, I’m not sure what happened to your code. At the moment, I’m not seeing in my comment feed. That being said, I read it in my email and wanted to say that I think you make a really good point. I’ve definitely thought of setting this at my container component level. Thus, I show a different component if I have no data to show instead of just showing a different component at the presentational level. I think that makes a lot of sense, too.

      I hope what I got across was that you can use ternary operators in your presentational components should they need to show different things based on state. Such as in your case, show a “There are no items.”

      Thanks for the feedback!

      • Yeah, the code snippet was in other comment, which I edited a hundred times to see if Disqus could stop messing with its syntax.

        The approach is more than fine, my suggestion was more based on separation of concerns than on a mistake.

        That said, it would be nice to do a test and see which performs better if a container component controlling rendering over a state or the presentational component. I’m also new at this React/JSX/Component development world so I’m on the discovery/curious stage.

        Thanks for the response pal!

        • I’ve only been writing React for about 6 months, so I am learning every day, too. It would be interesting to find benchmarks between the two ways of doing this.

          • I’ll try to get something running over the week and share with you the results.

        • Yep, That’s how I would do it, too, if I did it at the Container level. Honestly, this might be the better way to do it. Especially since the DisplayItems component may display different content with an empty list returned by the fetch. Thanks for the input.

          For the record, I don’t believe you need to pass props to the constructor (and then super()) if you don’t use props within the constructor method. At least that is what I have done in the past and I have not had a problem with it.