Learning React : JSX
Ahmad Jamaly Rabib
Posted on May 25, 2023
I am continuing to learn React. It is my second day learning React. If you are only reading this article then you can also visit my experience of learning React on Day 1. 😄
Let's hope I will get the knowledge to work with React very soon and just not learn then forget. 😁😅
So, yesterday we stopped after creating a React element using the React.createElement()
method. 😎
Today we will learn about JSX-> JavaScript XML
.
JSX
looks almost like HTML and it is really easy to use while using React.
So I am creating a similar React component for the increment button that we did in vanilla JS yesterday. Let’s update in the increment.js
file.
const domContainer = document.querySelector('#root');
const reactIncrement = (
<div>
<h1 id="display">0</h1>
<div>
<button id="button">Increment +</button>
</div>
</div>
);
ReactDOM.render(reactIncrement, domContainer);
Here as we can see I have simply written JSX to render the element in the root div. Let me run the html now. But I got an error in the console. 😞
Uncaught SyntaxError: Unexpected token '<' (at increment.js)
The reason for this error is Javascript doesn't recognize the JSX tags we have used. Even though I renamed the increment.js
file to increment.jsx (As I am now using JSX :wink:)
it didn't work. 😟
To get rid of this situation at last we found a way. We need to use a transpiler.
Transpilers are tools that convert one programming language into another language. 😲
In this case of React we will use Babel as a Transpiler. Babel will convert our JSX codes to vanilla JS.
There are also other use cases of Babel to help us coding without worring about the compatibility of different browsers. 😍
Here I checked my JSX code in babel.io website how it converted our JSX code to JS.
So let's go to babel website -> setup -> In the browser link and copy the babel script to our html file. Also let's add the increment.js script type to "text/babel"
.
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel" src="./increment.jsx"></script>
Now when we run the html in the browser we can see that the counter button and display is appearing and there is no console error.
- Let's add the increment functionality in the JS file. Let's first create an Increment method.
const Increment = () => {};
- Now let's copy the JSX codes we wrote before in the
increment.js
file inside the function, so that this Increment method returns that JSX code.
const Increment = () => {
return (
<div>
<h1 id="display">0</h1>
<div>
<button id="button">Increment +</button>
</div>
</div>
);
}
// Render Increment
ReactDOM.render(<Increment />, domContainer);
We are still viewing the same button and display with no functionality update till now. 😒
Now let's copy the increment functionality from the vanilla JS code that we wrote yesterday in our increment.js
file.
const domContainer = document.querySelector('#root');
const Increment = () => {
return (
<div>
<h1 id="display">0</h1>
<div>
<button id="button">Increment +</button>
</div>
</div>
);
}
let number = 0;
let button = document.querySelector('#button');
let display = document.querySelector('#display');
button.addEventListener('click', () => {
number++;
display.textContent = number;
});
ReactDOM.render(<Increment />, domContainer);
Did we get what we wanted? No! 😞
I got a console error after copying this.
So from the console error we found that the button is null. That means the button is not defined. So it seems we are calling the button event even before the button is initialized and rendered by calling the Increment
function.
So now let's render the elements first before calling the button.
ReactDOM.render(<Increment />, domContainer);
let number = 0;
let button = document.querySelector('#button');
let display = document.querySelector('#display');
button.addEventListener('click', () => {
number++;
display.textContent = number;
});
It works now!
But does it solve the problem? Can we use multiple components this way? Let's say we want two counters. Will it work? This is the reason we are working with React right?
The answer is no. 😭 We still haven't achieved what we want.
I tried adding the Increment component multiple times in the render.
ReactDOM.render(<><Increment /><Increment /><Increment /></>, domContainer);
The functionality should work independently, but it didn't.
In the above image we saw that only the first component is working but the others aren't.
The main reason for the above issue is that we aren't doing things in React way. Now let's do our coding in the React way. 💪
React tells us that we shouldn't manipulate DOM. But in our code we are still selecting DOM components, creating counter
variable then updating counter
using DOM manipulation. Which is actually prohibited in React.
So let's first remove our button and display counter functionality code.
To achieve this functionality using React we need to use State.
State is a built-in React object which is used to contain data or information about the component.
So in our counter functionality what is the state? This is our number
variable. Because only this data is changing and based on this our components' content is changing.
Now let's use this knowledge to create a State inside the Increment function.
const Increment = () => {
const counter = React.useState(0);
...
};
So what did I do there? I am using useState
and setting an initial value which is 0
in this case. Let's do a console.log(counter)
.
So, it returns an array which has two elements.
The first one is the value we set for the state and the second one is a function.
This function actually helps us by returning an updated value based on the parameter we will pass to the function.
So, this function updates the state and triggers a re-render of our component.
This can be used like this:
const [state, setState] = React.useState(initialValue);
Let's update our Increment
method now.
const [counter, setCounter] = React.useState(0);
Here we created the setCounter
function which we will call during the button click event. So our updated button will be:
<button id="button" onClick={ () => setCounter(counter + 1) }>Increment +</button>
I am using JSX. The onClick
function isn't the same as normal HTML. Couldn't find the issue the first time. Also I am using curly braces {}
not quotation "
like we used to use in HTML. Found these differences in JSX for now. I need to get used to it 😆
To show that counter in the display we will update our display area where we will bind the counter
variable inside h1
.
<h1 id="display">{ counter }</h1>
So after the updates I have now successfully created a React component, which is reusable and can be used several times. And most interestingly I can call this multiple times and can have multiple independent components without writing more codes. 😅
This is my JS code now.
const Increment = () => {
const [counter, setCounter] = React.useState(0);
return (
<div>
<h1 id="display">{ counter }</h1>
<div>
<button id="button" onClick={ () => setCounter(counter + 1) }>Increment +</button>
</div>
</div>
);
};
ReactDOM.render(<div className="container"><Increment /><Increment /><Increment /></div>, domContainer);
I have called the Increment method 3 times and it is now working fine!
Here is the github link for the two projects I have worked till now.
This is all for today. I will try to learn about React DOM tomorrow. Hopefully write something from that. Till then bye! 👋
Posted on May 25, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.