JSX Elements

React uses the createElement() function from the React global to compile JSX syntax to JavaScript so that it can be understood by web browsers. Therefore defining JSX elements like the below.

const element = ( 
    <p>I am an element</p>
);

Is the same as doing:

const element = React.createElement(
  'p',
  null,
  'I am an element'
);

As seen above and also in the Basic JSX Syntax post, createElement() can take three parameters.

  • type – This can be either a tag name string (such as ‘div’ or ‘span’), a React component type (a class or a function), or a React fragment type.
  • props – Properties of the element. For example, passing in {foo: 'bar'} results in the element having a foo="bar" property.
  • children – Child content. Using the example above, we’d get <p>I am an element</>

One property that will be commonly added to HTML elements is a class. Logically, you would think to pass in {class: 'some-class'} as the props parameter in createElement().

However, as class is a reserved keyword in JavaScript, className is used in React.

const element = ( 
     <p className="some-class">I am an element</p>
);

const anotherElement = React.createElement(
  'p',
  {className: 'some-class'},
  'I am an element'
);

In HTML5, it is preferred to use just one tag for elements such as <img>, <input> and <br>. However, when using JSX, you need to include the self-closing tag.

const elements = (
    <div>
        <img src="images/image_1.jpg" />
        <br />
    </div>
);

React does not just handle plain text when defining elements and using them in createElement(), you can also embed expressions as long as the expression resides in a pair of curly braces.

const element = ( 
     <p className="some-class">The answer to 2 + 2 is: {2+2}</p>
);

This tells the compiler to treat any expressions within the curly braces as pure JavaScript. You can also use curly braces to inject variables.

const paragraphText = 'foo bar baz';
const element = ( 
     <p className="some-class">{paragraphText}</p>
);

As well as adding an event listener, such as an onClick attribute whose value is a function contained in curly braces.

const myFunc = function() {
    alert('You\'ve clicked me!');
};

const element = <div onClick={myFunc}>Click Me!</div>;

ReactDOM.render(
    element, 
    document.getElementById('root')
);

This is all very convenient, however there is a slight pitfall in JSX in that you cannot use conditional statements. The below code therefore would not compile to valid JavaScript.

const element = (
    <p>
        {
            if (!loggedIn) {
                'Welcome Guest!'
            }
        }
    </p>
);

ReactDOM.render(element, document.getElementById('root'));

There are workaround for this, including moving the expression outside of the JSX definition.

var welcomeText = 'Welcome back!';

if (!loggedIn) {
    welcomeText = 'Welcome Guest!';
}

const element = <p>{welcomeText}</p>;

ReactDOM.render(element, document.getElementById('root'));

If you’ve only got simple conditional statements, you can also use ternary expressions rather than moving the conditional statement. More complex conditional statements, for readability benefits, should probably be moved outside of the JSX.

const element = <p>{!loggedIn ? 'Welcome Guest!' : 'Welcome back!'}</p>;