React JSX - How to do it the right way - Part I

Usually, when developing a website, you'll need some dynamical rendering, like a listing of items, showing some element under a certain condition and so on.
You're all aware of the standard JS syntax - a for loop, or an if/else - but when you try to write those under a render method in React, you'll most likely get some weird looking errors.

In this, the first part of React JSX series, we will take a look at how to correctly loop through arrays the reactive way.

Please note that all of the examples below apply as well to React Native!

Using loops inside React render methods

Let's say you have an array of movies and that you need to display the Movie component for each of them.

Most of us have tried this at some point:

render() {
    return (
        <div>
            {
                // this won't work!
            }
            {
                for (var i=0; i < movies.length; i++) {
                    <Movie movie={movie} />
                }
            } 
        </div>
    )
}

This, however, won't work. Why? Think of it like you're just calling JavaScript functions. You can't put a for loop as a parameter when calling a function!

Well, how to do it then? There are a few ways.
You can go through a for loop above the return statement in render method and fill in a list you'll pass in return:

render() {
    const movieItems = [];
    for (var i=0; i < movies.length; i++) {
        movieItems.push(<Movie movie={movie} />);
    }
    return (
        <div>
            {
                movieItems
            } 
        </div>
    )
}

This, however, is not a neat way as it's polluting the render method. To make render more readable, better move the for loop outside of it and then call it as a function:

renderMovies(movies) {
    const movieItems = [];
    for (var i=0; i < movies.length; i++) {
        movieItems.push(<Movie movie={movie} />);
    }
    return movieItems;
}

render() {
    return (
        <div>
            {
                this.renderMovies(movies)
            } 
        </div>
    )
}

This looks a bit better now. Still, you are using the for loop which doesn't really look so nice. The for should be used when you need to render something a certain number of times. When you have an object or an array instead, there are neater ways.

So, let's switch to using the map from JS Arrays:

renderMovies(movies) {
    // This is ES6 syntax! You'll need babel configured to use it!
    // You can still use the standard function syntax,
    // but ES6 is definitely something that'll easen your life.
    return movies.map((movie) => {
        return (
            <Movie movie={movie} />
        );
    });
}

render() {
    return (
        <div>
            {
                this.renderMovies(movies)
            } 
        </div>
    )
}

Now, this looks good! Yet, it might look a bit bulky for being just a simple listing you can do in one single place. However, the map syntax you can actually use directly in a return statement. Why? Because the map function basically passes a freshly created array, compared to the for loop which is just a bulk of code.

render() {
    return (
        <div>
            {
                // This is shortened syntax, for where we don't need to manipulate the actual items before rendering them
            }
            {
                movies.map((movie) => <Movie movie={movie} />)
            } 
        </div>
    )
}

When you need to manipulate the actual item in the list before rendering it, you can do it this way:

render() {
    return (
        <div>
            {
                movies.map((movie) => {
                    // do something with a movie here
                    return (
                        <Movie movie={movie} />
                    );
                })
            } 
        </div>
    )
}

Now, again, if there's a lot of manipulating to be done for a single item, doing it inside a return statement might unnecessarily pollute the render method. In that case, better move this code out of the render method. Here's an example:

renderMovie(movie) {
    // do something with a movie here
    return (
        <Movie movie={movie} />
    );
}

render() {
    return (
        <div>
            {
                // map will automatically pass the list item to our function
            }
            {
                movies.map(this.renderMovie)
            } 
        </div>
    )
}

All of the previous can also be used for JavaScript objects, with slight adaptation - you won't be mapping through the object, but through the list of the keys of the object:

render() {
    return (
        <div>
            {
                // You can as well use lodash keys function (_.keys)
                // instead of Object.keys, but it functions the same way
            }
            {
                Object.keys(moviesObject).map((movieKey) => {
                    const movie = moviesObject[movieKey];
                    return (
                        <Movie
                            key={movieKey}
                            movie={movie}
                        />
                    );
                })
            } 
        </div>
    )
}

Keep in mind that all of the codes above are just examples, pseudo codes. Always send the key prop to the items you're rendering and keep it unique, avoiding array indexes.

Now you know multiple ways on how to loop through arrays in React! Which way you'll use is up to you and the occasion, sometimes one will be more suitable than the other.

Thank you for your time and good luck with coding!

Part II is out! Read about conditional rendering in React now!

Did you like this article? Subscribe and stay tuned when new React articles come out!

Get the latest posts
delivered right to your inbox.

or subscribe via RSS with Feedly!