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.
<div className="container"> <h2 className="country-name">Country Name: {props.name}</h2> <p className="capital">Capital: {props.capital}</p> <p className="population">Population: {props.population}</p> </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 in order 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 is works. Lets 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.
function Country(props) { return ( <div className="container"> <h2 className="country-name">Country Name: {props.name}</h2> <p className="population">Population: {props.population}</p> <p className="area"> Area: {props.area} km<sup>2</sup> </p> <p className="positive"> {props.democracy && `${props.name} is a Democracy.`} </p> <p className="negative"> {props.population / props.area > 200 && `${props.name} is densly populated.`} </p> <p> {props.continent == "Asia" ? `${props.name} is in Asia.` : `${props.name} is not in Asia.`} </p> </div> ); } let countryElement = ( <> <Country name="India" population={1389637446} area={3287263} democracy continent="Asia" /> <Country name="United States" population={332800000} area={9833520} democracy continent="North America" /> </> ); let rootElement = document.getElementById("root"); 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
. The basically means that the following line
{props.democracy && `${props.name} is a Democracy.`}
effectively becomes
{true && `${props.name} is a Democracy.`}
In the next line, we do something slightly more complicated and check if 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.
Lets 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 bunch of <li>
elements along the way. We will use the map()
method to create our list and 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.
function Country(props) { let popDensity = props.population/props.area; let popFeature = popDensity > 200 ? 'sparsely' : 'densly'; let isDemocracy = props.democracy && `${props.name} is a Democracy.`; let states = props.largestStates.map(state => <li>{state}</li>); return ( <div className="container"> <h2 className="country-name">Country Name: {props.name}</h2> <p className="population">Population: {props.population}</p> <p className="area">Area: {props.area} km<sup>2</sup></p> <p>{isDemocracy}</p> <p>It is {popFeature} populated.</p> <h3>Five Largest States:</h3> <ol> {states} </ol> </div> ); } let countryElement = ( <> <Country name="United States" population={332800000} area={9833520} democracy largestStates={["Alaska", "Texas", "California", "Montana", "New Mexico"]} /> </> ); let rootElement = document.getElementById("root"); ReactDOM.createRoot(rootElement).render(countryElement);
Also remember that you can only use expressions inside the curly braces so 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 set everything up in JavaScript beforehand and use JSX to then create our UI based on the final data.
No comments:
Post a Comment