Using JavaScript expressions
As we saw in the preceding section, JSX has special syntax that lets us embed JavaScript expressions. Any time we render JSX content, expressions in the markup are evaluated. This is the dynamic aspect of JSX content, and in this section, you'll learn how to use expressions to set property values and element text content. You'll also learn how to map collections of data to JSX elements.
Dynamic property values and text
Some HTML property or text values are static, meaning that they don't change as the JSX is re-rendered. Other values, the values of properties or text, are based on data that's found elsewhere in the application. Remember, React is just the view layer. Let's look at an example so that you can get a feel for what the JavaScript expression syntax looks like in JSX markup:
import React from 'react'; import { render } from 'react-dom'; // These constants are passed into the JSX // markup using the JavaScript expression syntax. const enabled = false; const text = 'A Button'; const placeholder = 'input value...'; const size = 50; // We're rendering a "<button>" and an "<input>" // element, both of which use the "{}" JavaScript // expression syntax to fill in property, and text // values. render(( <section> <button disabled={!enabled}>{text}</button> <input placeholder={placeholder} size={size} /> </section> ), document.getElementById('app') );
Anything that is a valid JavaScript expression can go in between the braces: {}
. For properties and text, this is often a variable name or object property. Notice in this example, that the !enabled
expression computes a boolean value. Here's what the rendered output looks like:
Note
If you're following along with the downloadable companion code, which I strongly recommend doing, try playing with these values, and seeing how the rendered HTML changes.
Mapping collections to elements
Sometimes we need to write JavaScript expressions that change the structure of our markup. In the preceding section, we looked at using JavaScript expression syntax to dynamically change the property values of JSX elements. What about when we need to add or remove elements based on a JavaScript collection?
Note
Throughout the book, when I refer to a JavaScript collection, I'm referring to both plain objects and arrays. Or more generally, anything that's iterable.
The best way to control JSX elements dynamically is to map them from a collection. Let's look at an example of how this is done:
import React from 'react'; import { render } from 'react-dom'; // An array that we want to render as a list... const array = [ 'First', 'Second', 'Third', ]; // An object that we want to render as a list... const object = { first: 1, second: 2, third: 3, }; render(( <section> <h1>Array</h1> { /* Maps "array" to an array of "<li>"s. Note the "key" property on "<li>". This is necessary for performance reasons, and React will warn us if it's missing. */ } <ul> {array.map(i => ( <li key={i}>{i}</li> ))} </ul> <h1>Object</h1> { /* Maps "object" to an array of "<li>"s. Note that we have to use "Object.keys()" before calling "map()" and that we have to lookup the value using the key "i". */ } <ul> {Object.keys(object).map(i => ( <li key={i}> <strong>{i}: </strong>{object[i]} </li> ))} </ul> </section> ), document.getElementById('app') );
The first collection is an array called array
, populated with string items. Moving down to the JSX markup, you can see that we're making a call to array.map()
, which will return a new array. The mapping function is actually returning a JSX element (<li>
), meaning that each item in the array is now represented in the markup.
Note
The result of evaluating this expression is an array. Don't worry; JSX knows how to render arrays of elements.
The object collection uses the same technique, except we have to call Object.keys()
and then map this array. What's nice about mapping collections to JSX elements on the page is that we can drive the structure of React components based on collection data. This means that we don't have to rely on imperative logic to control the UI.
Here's what the rendered output looks like: