React basics Full

React basics Full

What is JSX?



In the previous module we used the following code to show an output using React:ReactDOM.render(
<h1>Hello, React!</h1>,
document.getElementById('root')
);

Try it on StackBlitz



Let's start to break down the code and understand each part of it.
We will start with the <h1>Hello, React!</h1> element.

As you can see, the element is not in quotes to represent a string. It's like an HTML element, however we use it right in the JavaScript code!
This is called JSX, and it is a syntax extension to JavaScript. It allows us to build UI elements right in the JavaScript code!
React does not require using JSX, however, it is common practice in the React community to use JSX as it eases the development of user interfaces, as well as allows React to show useful error and warning messages.



Intro to JSX



Let's have a look at our code again:ReactDOM.render(
<h1>Hello, React!</h1>,
document.getElementById('root')
);

The code calls React's render method, and passes it two arguments, a JSX element and a container. The render method displays the provided element in the container, which, in our case, is the HTML element with id="root".

Try it on StackBlitz
When you call the render method, any existing content of the container gets replaced. That is why, usually, the containers are empty in the HTML.





Expressions in JSX



We can use any JavaScript expression inside JSX using curly braces.

For example:
const name = "David";
const el = <p>Hello, {name}</p>;

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

Try it on StackBlitz
In the example above, we use the variable name in the JSX element.
As you can see, JSX can be used just like JavaScript expressions. You can assign a JSX expression to a variable, return it from a function, etc.


Attributes in JSX



We can specify attributes using quotes, just like in HTML:<div id="name"></div>
When using a JavaScript expression as the attributes value, the quotes should not be used:<div id={user.id}></div>
React DOM uses camelCase property naming convention instead of HTML attribute names.
For example, class becomes className in JSX.




How Does JSX Work?



When the JSX expressions are compiled, they are converted into JavaScript objects, representing React elements.
React then uses these elements to build the corresponding HTML DOM and display it in the browser.

Let's create a counter app, that increments a counter variable every second and displays it on the page as a paragraph:let counter = 0;

function show() {
counter++;
const el = <p>{counter}</p>;
ReactDOM.render(
el, document.getElementById('root')
);
}

setInterval(show, 1000);

Try it on StackBlitz

We use setInterval to call the show function every second and render the counter element on the page.

One of the great features of React is that it updates only the elements that need an update. You can inspect the HTML output of the example above and see that only the text in the paragraph gets updated every second.
In practice, most React apps call ReactDOM.render() once.
We will learn how to update elements without calling the render method in the next lessons.





Virtual DOM



We learned in the previous part that React updates only the elements that are necessary.
This allows React apps to be much faster than apps built with other front-end technologies.

But how does React achieve that?
React uses a Virtual DOM, which is a lightweight representation of the DOM.
When an element gets changed, it is first updated in the Virtual DOM. That process is fast, as the virtual DOM is represented by simple objects.

After that, React compares the Virtual DOM to its previous state and only applies the DOM updates necessary to bring the DOM to the desired state.
DOM stands for Document Object Model and is a tree-like representation of the HTML page.
Check out our JavaScript Tutorial to learn more about DOM.




Components



Components let you split the page into independent and reusable parts.

Let's visualize this by taking a look at a piece of the SoloLearn Discussions page:
Notice that the page can be split into multiple parts. Each of these "parts" are a component.
The heading is a component, the "new question" button is a component, and the search bar is its own component.
This makes organizing the page leaps and bounds easier, but even more importantly, components allow us as the developers to separate concerns from one another.
Separation of concerns is a programming principle that states that each concern should be separated into individual pieces.
For example, in the diagram above, the "new question" button (2) should be clicked if a user wanted to add a new question, whereas the search bar (3) would be used if the user wanted to search the existing questions.




Functional Components



In React, there are two types of components that you can use: Functional Components and Class Components.
In this part, we will talk about functional components.

A functional component is a simple JavaScript function:function Hello() {
return <h1>Hello world.</h1>;
}

The code above defined a functional component called Hello, that returns a simple React element.
Notice that the name of the functional component begins with a capital letter. This is absolutely critical. If we start the name of a component with a lowercase letter, the browser will treat our component like a regular HTML element instead of a Component.



Rendering Components



In order to display the component, we need to create the corresponding JSX element.

For example, for our user-defined component Hello:const el = <Hello />;
Now, we can use our user-defined element and render it on the page:function Hello() {
return <h1>Hello world.</h1>;
}

const el = <Hello />;
ReactDOM.render(
el,
document.getElementById('root')
);

Try it on StackBlitz
Remember, all component names need to start with a capital letter.



Class Components



Class components are typically used when there are more advanced user interactions, like forms, and animations.

All class components need to extend the React.Component class.

We can rewrite our Hello functional component as a class component:class Hello extends React.Component {
render() {
return <h1>Hello world.</h1>;
}
}

Try it on StackBlitz
Class components need to have a render method, which is in charge of telling what the page should show.
We will learn about the features and differences of functional and class components in the next lessons.





Props



Functional components can accept arguments, similar to JavaScript functions. These arguments are called props, and represent an object.

For example, we can use props in our Hello component:function Hello(props) {
return <p>Hello, {props.name}!</p>;
}

Now, we can add a name attribute to our element:const el = <Hello name="David" />;
The attribute value will be passed to the component when rendered.

props-example?file=index.js">Try it on StackBlitz
An element can have multiple custom attributes, which will be passed to the component using the props object. You can use any custom names for your attributes.





Components using Components



Components can use other components to generate an output.

For example:function App() {
return <div>
<Hello name="David" />
<Hello name="James" />
<Hello name="Amy" />
</div>;
}

Here, our App component uses the Hello component three times, each times with a new name attribute.

[a href="https://stackblitz.com/edit/react-functional-component-props-example-2?file=index.js"]Try it on StackBlitz[/a]
Generally, it is a good practice to split complex components into multiple smaller components, that are reusable.
For example, a Post component can use an Avatar component, an Image component, a Date component, etc.







Props in Class Components



Props can be accessed in class components using this.props.

For example:class Hello extends React.Component {
render() {
return <p>Hello, {this.props.name}!</p>;
}
}

props-example?file=index.js">Try it on StackBlitz

An important thing to consider is that props are read-only, meaning components cannot modify their props.
Interactive apps generally need to change data and the page elements.
We will learn how to change the output of components using state in the next lesson.





An Example



Now that we know how to create components and pass them data, let's create a shopping list.

Each item in our list will have a name and a price.

For example:
<Item name="Cheese" price="4.99" />
The Item component will render a simple div element with the data:function Item(props) {
return <div className="item">
<b>Name:</b> {props.name} <br />
<b>Price:</b> {props.price}
</div>;
}

Now we can use our component and create multiple items for our shopping list:<Item name="Cheese" price="4.99" />
<Item name="Bread" price="1.5" />
<Item name="Ice cream" price="24" />

Try it on StackBlitz
We have added some simple CSS styles to separate the items visually.
Tap Try it on StackBlitz to see the result and play around with the code.





State



Up until this point, we have learned how to pass data to components using props.

Many web apps need their components to change their data, for example, after user interaction (clicking a button, submitting a form, etc.).
However, props cannot be changed.

In order to allow components to manage and change their data, React provides a feature called state.
State is an object that is added as a property in class components.

For example:class Hello extends React.Component {
state = {
name: "James"
}

render() {
return <h1>Hello {this.state.name}.</h1>;
}
}

Try it on StackBlitz

As you can see, state is just a simple object, that contains key:value pairs.
Similar to props, the values can be accessed using this.state.

Now, when the component renders, the state is initialized with the given value and there will be a heading that says "Hello James.".

Try It on StackBlitz
The state object can contain multiple key:value pairs, separated by commas.





Changing State



State should not be modified directly. Instead, React provides a setState() method, that can be used to modify state.

For example:this.setState({
name: "James",
age: 25
});

You need to pass an object with the new key:value pairs to the setState method.

Why should we use setState, instead of simply changing the values of the object properties directly?
The answer uncovers one of the most useful features of React: when setState is called, React automatically re-renders the affected component with the new state!

Usually, the change in state happens in event handlers. We will look at an example in the next part!
When state changes using the setState method, React gets informed and immediately re-renders the component with the updated state.



Counter App



To better understand how state works, let's create a counter app, which increments the counter each time a button is clicked.
We start by creating our Counter component, which includes the counter and a button:class Counter extends React.Component {
state = {
counter: 0
}
render() {
return <div>
<p>{this.state.counter}</p>
<button>Increment</button>
</div>;
}
}

We have initialized our counter to the value 0 in the state.

Now, we need to add a click event handler to the button and increment the counter in the state.
Here is the final code:class Counter extends React.Component {
state = {
counter: 0
}
increment = () => {
this.setState({
counter: this.state.counter+1});

}
render() {
return <div>
<p>{this.state.counter}</p>
<button onClick={this.increment}>Increment</button>
</div>;
}
}

Try it on StackBlitz


The onClick event calls the increment function of our component, which uses setState to change the value of our counter. When the state is changed, React automatically triggers a re-render of the component.

Tap Try it on StackBlitz to see the counter in action!
Notice that the event handler uses camelCase syntax and that the handler function is passed in curly braces.
We will cover event handlers in more detail in the next lessons.










Props vs State



As a recap, here is a summary of the main differences between props and state:

- We use props to pass data to components.
- Components use state to manage their data.
- Props are read-only and cannot be modified.
- State can be modified by its component using the setState() method.
- The setState() method results in re-rendering the component affected.
Components that have state are called stateful, while components that do not use state are called stateless.


Hooks



Earlier version of React allowed to use state only with class components.
In recent iterations of React, a new feature called hooks was introduced, allowing to use state inside of functional components.

First, we need to import the useState hook:import React, { useState } from 'react';
useState returns a pair, the current state value and a function, that lets you change the state.
useState takes one argument, which is the initial value of the state.

Let's look at an example:function Hello() {
const [name, setName] = useState("David");

return <h1>Hello {name}.</h1>;
}

Try it on StackBlitz

In the example above, we create a name state variable and a setName function. The square brackets syntax is called array destructuring. It assigns the name variable to the current state value, and setName to the function that allows to change the state. You can name these variables anything you like.
Then, we pass "David" as the initial value for our name variable to useState().
You can create multiple state variables with their corresponding set methods. Just use separate statements for each variable using the useState hook.


Counter App using Hooks



Now we can rewrite our Counter app from the previous lesson using a functional component and hooks!

Here is the code:function Counter() {
const [counter, setCounter] = useState(0);

function increment() {
setCounter(counter+1);
}

return <div>
<p>{counter}</p>
<button onClick={increment}>
Increment
</button>
</div>;
}

Try it on StackBlitz

As you can see, compared to the class component, the code is much shorter and easier to read and understand. That was one of the reasons why the React team created Hooks.
Remember, hooks can only be used inside functional components.
Hooks are functions that allow to "hook into" React features from function components.





Lifecycle Methods



React provides special lifecycle methods for class components, which are called when components are mounted, updated or unmounted.

componentDidUpdate



Another lifecycle method is componentDidUpdate(), which is called when a component is updated in the DOM.

We can, for example, alert the current counter value when it is incremented:componentDidUpdate() {
alert("Number of clicks: " + this.state.counter);
}

Try it on StackBlitz
componentDidUpdate() is only called when the component is updated.
Mounting is the process when a component is rendered on the page.
Unmounting is the process when a component is removed from the page.

The componentDidMount method is called when a component is rendered on the page.

For example, we can use componentDidMount in our Counter app to set the initial value of the counter:componentDidMount() {
this.setState({counter: 42});
}

Try it on StackBlitz

This will set an initial value of the counter when the component is rendered.

componentDidMount is typically used for populating the state inside of a component when it initially mounts to the DOM.
Similarly, the componentWillUnmount() lifecycle method is called right before the component is removed from the DOM. It can be used to free up resources taken by the component.



The useEffect Hook



The lifecycle methods we covered are only available for class components.
However, React provides a special Hook called useEffect to make lifecycle methods available in functional components. It combines the componentDidMountcomponentDidUpdate, and componentWillUnmount methods into one.

For example, we can achieve the behavior of our last example using a functional Counter component:function Counter() {
const [counter, setCounter] = useState(0);

useEffect(() => {
alert("Number of clicks: " + counter);
});


function increment() {
setCounter(counter+1);
}
return <div>
<p>{counter}</p>
<button onClick={increment}>Increment</button>
</div>;
}

Try It on StackBlitz

When you run the code, you'll notice that the alert dialog appears also during the first render. This is caused by the fact that, by default, useEffect runs both, after the first render and after every update.

To call the method only when something changes, we can provide it a second argument:useEffect(() => {
//do something
}, [count]);

Now, the useEffect() method will run only if count changes.

To mimic componentWillUnmount, useEffect may return a function that cleans up after it:useEffect(() => {
// do something

return () => {
// cleanup
};

});

You can have multiple effects in the same component.
Just like with the useState hook, we need to import useEffect to be able to use it: import React, { useState, useEffect } from 'react';


Event Handling



Handling events in React is very similar to handling events in the DOM.

The only difference is that event names use camelCase syntax and the event handler needs to be passed in curly braces.

For example, to handle the click event on a button:<button onClick={handleClick}>
My Button
</button>

Clicking the button will call the handleClick function of the component.

Let's explore our Counter app:function Counter() {
const [counter, setCounter] = useState(0);

function increment() {
setCounter(counter+1);
}
return <div>
<p>{counter}</p>
<button onClick={increment}>Increment</button>
</div>;
}

Try it on StackBlitz

The onClick event calls the increment function, which is incrementing the counter state variable.
Check out the same Counter app built using a class component here.



Handling User Input



One of the common ways that users interact with web pages is through text fields.

We can handle user input in React using the onChange event of the text field.
When the value of the text field changes, the event handler is called, updating the value of the field in the component's state.
This way you always have the actual value of the text field in the state.

Let's make an app to convert Km to Miles. We will take the Km value from a text field and calculate the miles value upon input:function Converter() {
const [km, setKm] = useState(0);

function handleChange(e) {
setKm(e.target.value);
}
function convert(km) {
return (km/1.609).toFixed(2);
}

return <div>
<input type="text" value={km}
onChange={handleChange} />
<p> {km} km is {convert(km)} miles </p>
</div>;
}

Try it on StackBlitz

Our Converter component includes a text field, which calls the handleChange function when its value changes.
The handleChange function updates the state with the current value of the textfield, causing the component to re-render and show the corresponding miles value, which is calculated using the convert function.
The value of the text field is accessed via the e object, which represents the React event. It is passed to the event handler function as an argument and can be used to access the event object.


Forms



In the previous part, we learned how to handle user input in text fields. Text fields are usually part of a form.

Similar to the previous example, React form elements keep their state and update it based on user input.
This way you always have the data of your form at your disposal in the state.

To demonstrate this, we will create a form, that will add numbers every time the form is submitted and display the sum.
Our form contains an input field and a submit button:function AddForm() {
const [sum, setSum] = useState(0);
const [num, setNum] = useState(0);

function handleChange(e) {
setNum(e.target.value);
}

function handleSubmit(e) {
setSum(sum + Number(num));
e.preventDefault();
}

return <form onSubmit={handleSubmit}>
<input type="number" value={num} onChange={handleChange} />
<input type="submit" value="Add" />
<p> Sum is {sum} </p>
</form>;
}

Try it on StackBlitz

In the code above, the value of the input is controlled by React (we keep the value in the state).
When the form is submitted using the submit button, the handleSubmit function gets called, which updates the value of sum in the state.

An input form element whose value is controlled by React in this way is called a "controlled component".
Notice the e.preventDefault(); statement. This statement prevents the default behavior of the form, which, by default, reloads the page when submitted. In JavaScript we would use return false; for that, but in React we need to call preventDefault().




Lists



Web apps commonly contain repeating elements, such as lists or sections, where the same DOM element is repeated with a different data set.

Consider an array of strings:const arr = ["A", "B", "C"];
We need to render a list <li> element for each item in the array.
We can define a MyList component and pass it the array as a prop using a custom data attribute:<MyList data={arr} />
Now, when the array is accessible via props, we can write the component logic:function MyList(props) {
const arr = props.data;
const listItems = arr.map((val) =>
<li>{val}</li>
);
return <ul>{listItems}</ul>;
}

Try it on StackBlitz

We take the input array from the incoming props, loop through the array using the JavaScript map function and return a <li> element for each item.
The resulted array is stored in the listItems variable.
Then, the component returns the listItems array inside a <ul> tag.

The result:

This code results in a warning, saying that each element needs a unique key. We will look into keys in the next part.









Keys



Each element in a list must have a key attribute.
Keys act as a unique identity, identifying each element.
Usually, these are IDs from your data, or can be auto-generated indexes.

For example:const listItems = arr.map((val, index) =>
<li key={index}>{val}</li>
);

Try it on StackBlitz
Keys are important, because they uniquely identify elements, helping React understand which items have changed, are added, or are removed.
zxzx