1. Code
  2. JavaScript
  3. React

Learn React 18: Separating JavaScript and JSX

Scroll to top
60+ min read

Using JavaScript with JSX lets you write cleaner components with more complex data processing and logic.

In this lesson from our free full-length beginner course on React 18, you'll learn how. 

In our previous tutorial, we saw how using JSX to write the structure of our component results in cleaner, shorter, and easier-to-understand code compared to using vanilla JavaScript.

So far, we have only created our components using JSX where we didn't have to rely on logic or conditionals to determine the component structure. For example, the Country component simply outputs some text directly based on the props values we passed to it.

You will usually have to do at least a little processing of incoming props data when creating React components in real life. In this tutorial, our focus will be on learning how to do that properly by separating JavaScript and JSX.

Using JavaScript Expressions in JSX

JSX allows you to embed any valid JavaScript expression as long as it is within curly braces. We used this feature earlier to access values from the props object.

1
<div className="container">
2
  <h2 className="country-name">Country Name: {props.name}</h2>
3
  <p className="capital">Capital: {props.capital}</p>
4
  <p className="population">Population: {props.population}</p>
5
</div>

Expressions in JavaScript are pieces of code that ultimately resolve to a value. In the above example, props.name resolved to the country name. We could add the toUpperCase() method to capitalize the country name, and it would still work. You are allowed to do such simple operations within the curly brackets.

Using Conditionals Inside JSX

We can use the && operator to render an element conditionally in JSX based on the boolean value of an expression. Here is how it works. Let's say you write true && expression with the curly braces in JSX—this will resolve to expression. On the other hand, false && expression will always resolve to false, and nothing will be rendered.

We can rewrite our Country component so that it uses conditionals to output some statements based on the boolean value.

1
function Country(props) {
2
  return (
3
    <div className="container">
4
      <h2 className="country-name">Country Name: {props.name}</h2>

5
      <p className="population">Population: {props.population}</p>

6
      <p className="area">
7
        Area: {props.area} km<sup>2</sup>

8
      </p>

9
      <p className="positive">
10
        {props.democracy && `${props.name} is a Democracy.`}
11
      </p>

12
      <p className="negative">
13
        {props.population / props.area > 200 &&
14
          `${props.name} is densely populated.`}
15
      </p>

16
      <p>
17
        {props.continent == "Asia"
18
          ? `${props.name} is in Asia.`
19
          : `${props.name} is not in Asia.`}
20
      </p>

21
    </div>

22
  );
23
}
24
25
let countryElement = (
26
  <>
27
    <Country
28
      name="India"
29
      population={1389637446}
30
      area={3287263}
31
      democracy
32
      continent="Asia"
33
    />
34
    <Country
35
      name="United States"
36
      population={332800000}
37
      area={9833520}
38
      democracy
39
      continent="North America"
40
    />
41
  </>

42
);
43
44
let rootElement = document.getElementById("root");
45
ReactDOM.createRoot(rootElement).render(countryElement);

We pass a democracy prop to both our Country components. Its default value became true since we did not assign any value to it. As a result, props.democracy will return true. This basically means that the following line

1
{props.democracy && `${props.name} is a Democracy.`}

effectively becomes

1
{true && `${props.name} is a Democracy.`}

In the next line, we do something slightly more complicated and check if the population per unit area is over 200. If it goes over 200, we output a statement about population density.

You can use the ternary operator within curly braces when you want to render something irrespective of the value passed evaluating to positive or negative. This is what we did with the continent prop. Try your own conditional inside JSX in a similar manner.

Separating JavaScript and JSX

The beauty of JSX is that it is easy to read and allows us to construct complex component structures easily. However, introducing more and more logic using curly braces is counter-productive. The aim is to keep JSX as declarative as possible and handle the logic separately.

Let's say we want to list the five largest states of a country within our component. We could pass them along with other values as a prop. After that, we can iterate over the list of states and create a bunch of <li> elements along the way. We will use the map() method to create our list. It would work inside the curly braces with JSX as well, but everything looks cleaner and will be easier to maintain in the long run when we keep the logic part separate.

1
function Country(props) {
2
  
3
  let popDensity = props.population/props.area; 
4
  let popFeature = popDensity > 200 ? 'sparsely' : 'densely';
5
  
6
  let isDemocracy = props.democracy && `${props.name} is a Democracy.`;
7
  
8
  let states = props.largestStates.map(state => <li>{state}</li>);

9
 
10
  return (
11
    <div className="container">
12
      <h2 className="country-name">Country Name: {props.name}</h2>

13
      <p className="population">Population: {props.population}</p>

14
      <p className="area">Area: {props.area} km<sup>2</sup></p>
15
      <p>{isDemocracy}</p>

16
      <p>It is {popFeature} populated.</p>

17
      <h3>Five Largest States:</h3>

18
      <ol>
19
        {states}
20
      </ol>

21
    </div>

22
  );
23
}
24
25
let countryElement = (
26
  <>
27
    <Country
28
      name="United States"
29
      population={332800000}
30
      area={9833520}
31
      democracy
32
      largestStates={["Alaska", "Texas", "California", "Montana", "New Mexico"]}
33
    />

34
  </>

35
);
36
37
let rootElement = document.getElementById("root");
38
ReactDOM.createRoot(rootElement).render(countryElement);

Also, remember that you can only use expressions inside the curly braces, so any code with if statements or for loops will have to be placed outside of JSX anyway. You can get away with using immediately invoked function expressions, but keeping the logic separate is a good practice and much more productive in the long term.

Final Thoughts

React does not aim to separate markup and logic by placing them in separate files. Instead, it relies on components to split your UI into multiple entities which can function independently. It is our job to keep our logic separate from the markup within the component. The best way to do so is to set everything up in JavaScript beforehand and use JSX to then create our UI based on the final data.

Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.