React refersher
Tags: javascript, webdev, beginners, react
Published: 2024-01-20 15:57:20

# React

I recently decided to refresh my React skills, since it has been a very long time since I did something with any frontend technologies. React is one of the most used front-end JS libraries that is used to build user interfaces for web apps and native apps(React Native).

### How does React work?

React maintains a Virtual DOM, similar to the actual DOM. DOM is a Document Object Model, which is essentially a tree. React works fast by updating the virtual DOM first which is cheaper compared to updating the actual DOM. Once it does that, it effectively reconstructs the actual DOM to push only the changes. 

### What is JSX?

React uses JSX which is nothing but syntactic sugar. Everything written in JSX is converted to JS.

```jsx
const para = <p>Hi World</p>
```
gets converted to
```js
const tag = React.createElement("p", {}, "Hi World")
```

One thing we observe with JSX that is different from HTML is that we can't use *class*, instead we use *className*. This is because *class* is a reserved keyword. There are a few subtleties like this in JSX which we need to be careful about.

### What are components?

React is a component-based front-end library. This allows us to essentially build our UI as small reusable components. Every React app is a tree of React Components.

### Types of Components

React has 2 types of components.

- Class-based
- Functional

#### Class Based Components

Let's see how class-based components look like first

```js
import React, {Component} from 'react'
class Test extends Component {
    render() {
        return <div>Hi There!</div>
    }
}
```

As we can see, we create a separate file for a component. Then we need to import React and Component. We create a class called Test(name of our component). Then we use the render method to define what to display. But this is history, it's legacy code now as functional components have started to take precedence.

#### Functional Components

```js
import React from 'react'

const Test = () => {
    return <div>Hi There!</div>
}
```

Here too, we import a React library, but this can be skipped in the latest versions. Then we just need to create a function(can be named or arrow). That's it.

### Setting up a project

We can either
- setup a project manually by using Webpack and Babel 
- using create-react-app command

We will go with create-react-app as it's far easier. But if finer control is required better to go with the first approach.

### What is create-react-app?

create-react-app is a tool to generate the starter project. It's officially supported by the React team. To create a project just create a project directory and run the below command.

```bash
npx create-react-app ./
```

This creates our React Project. We can start the project by running the below command.

```bash
npm start
```

The project will be hosted on port 3000 on localhost.

### React Project structure

Let's look at the directories the create-react-app had created to understand what files are required for React to run.

The first file we need to look at is *package.json*. Here we will find a list of dependencies for the project. We will find the react libraries as well here.

```json
"dependencies": {
  "@testing-library/jest-dom": "^5.17.0",
  "@testing-library/react": "^13.4.0",
  "@testing-library/user-event": "^13.5.0",
  "react": "^18.2.0",
  "react-dom": "^18.2.0",
  "react-scripts": "5.0.1",
  "web-vitals": "^2.1.4"
}
```

Next, in the public directory, we find the *index.html*. The main thing we need to look at is the root div. React injects the entire app inside the root tag.

```HTML
<div id="root"></div>
```

This is done in the *index.js* file found under the src directory. Below is a sample of the file.

```js
import React from "react";
import ReactDOM  from "react-dom";

import App from './App';

ReactDOM.render(<App/>, document.getElementById("root"));
```

Here the ReactDOM is imported with React library. We use ReactDOM only once in the entire app. We use ReactDOM.render with the component we want to inject and the target DOM element. React injects the App component into the root element. This is the basis of how React works.

The next file is *App.js* inside the src directory. It's the place where we are defining what to render. 

### React in action

The main feature of React is the power to write HTML inside Javascript and vice versa. Inside a pair of curly braces, we can put and valid Javascript code.

For instance, we can start with a clean App.js. Remember App.js is a component. 

```jsx
import './App.css';

const App = () => {
  return (
    <div className="App">
      <h1>Hi There</h1>
    </div>
  );
}

export default App;
```

This renders a simple **Hi There** on the page. Let's first understand what is happening here.

- We are importing a css file for styling. 
- We are defining a functional component called App using the arrow function.
- We export the App function, so it can be used wherever the file gets imported.

Now, we can start playing with it. We can define a variable and display the same to the user. 

```jsx
const App = () => {
  const name = "John Doe";
  return (
    <div className="App">
      <h1>Hi {name}</h1>
    </div>
  );
}
```

React renders us **Hi John Doe**. It evaluates the name variable to get the actual value and shows us the result. 

We can make the same conditional based on a parameter.

```jsx
const App = () => {
  const name = "John Doe";
  const isNameEnabled = false;
  return (
    <div className="App">
      <h1>Hi {isNameEnanled ? name : "there"}</h1>
    </div>
  );
}
```

React renders **Hi there**. Here we have used a ternary operator to display the name conditonally. Similarly, we can perform calculations, computations, etc.

Now, let's assume we need to render multiple elements, we usually do that with divs. But a cleaner approach to stop the page from having multiple inner divs is using *fragments*.

```jsx
import React from 'react';

const MultipleElements = () => (
  <>
    <h1>Hi</h1>
    <p>There</p>
  </>
);
```

Note this is a newer React feature, so legacy apps might not support it. If we don't nest them, we run into the error "Adjacent JSX elements must be wrapped in an enclosing tag". So, be careful with this.

Moving forward, we will start creating components.

### Creating and importing components

One of the selling points of React is that we can create smaller components and embed them into parent components. This way we can reuse the components in multiple places.

We will look at an example below.

```jsx
const Person = () => {
  return (
    <>
      <h1>First Name: John</h1>
      <h1>Last Name: Doe</h1>
      <h1>Age: Unknown</h1>
    </>
  );
}

const App = () => {
  return (
    <div className="App">
      <Person />
    </div>
  )
}
```

This will render us with text defined in the Person Component. This is how we import one Component into another.

### What are props?

To pass data to our Components we use **props**. Props are arguments passed into React Components. We pass them as HTML attributes. We use props to pass data from one component to another (Parent to Child). Data passed in props is read-only and cannot be modified by the received component. 

We will look at the same example above with props.

```jsx
const Person = (props) => {
  return (
    <>
      <h1>First Name: {props.firstName}</h1>
      <h1>Last Name: {props.lastName}</h1>
      <h1>Age: {props.age}</h1>
    </>
  );
}

const App = () => {
  return (
    <div className="App">
      <Person firstName='John' lastName='Doe' age={20}/>
      <Person firstName='Jane' lastName='Doe' age={25}/>
    </div>
  )
}
```

As we can see, in the Child component we get the props argument and use the attributes passed from the parent component.

### What is state?

State is a JS object used by React to represent the component's state(maybe a counter instance). It is completely managed by the Component it's present in. Whenever the state changes, the component re-renders. The state object is where we store property values that belong to the component. State data can be modified by its component, but is private.

We will look at a simple counter using state.

```jsx
import { useState } from 'react';
import './App.css';

const App = () => {
  const [counter, setCounter] = useState(0);
  return (
    <div className='App'>
      <button onClick={() => {setCounter((prevCounter) => prevCounter - 1)}}>-</button>
      <h1>{counter}</h1>
      <button onClick={() => {setCounter((prevCounter) => prevCounter + 1)}}>+</button>
    </div>
  );
}

export default App;
```

To use state we need to import the react hook called useState. There are a few hooks that React gives, it's better to know of them. 

useState accepts an initial state and returns 2 values. They are the current state and a function to update the state. We should never update the state directly and always use this function.

So here we have defined the current state as 0, the current state is *counter*, and the *setCounter* is the function to update the state. This helps us keep track of the counter and as and when the counter gets updated the component gets re-rendered. If we don't use state and directly do the same, the component doesn't get re-rendered and the value remains the same.

Another important hook is useEffect. It's used to perform side effects on the components. For instance, if we want to show an alert every time the counter is updated, we can do something like this.

```jsx
useEffect(() => {
  alert("Counter has been updated to " + counter);
}, [counter])
```

useEffect takes in 2 arguments. The function it has to call, and what it is dependent on. 

- If we don't pass the second argument, it gets triggered on every re-render. The below block will always make the counter to 0, whenever it changes. (Just for example)
```jsx
useEffect(() => {
    setCounter(0);
  });
```
- If we pass an empty array, it gets triggered only on the first render. The below block sets the counter to 100 on the first render.
```jsx
useEffect(() => {
    setCounter(100);
  }, []);
```
- If we pass the dependent element, it gets triggered when the value gets updated. This block just alerts the counter whenever the counter gets changed.
```jsx
useEffect(() => {
  alert("Counter has been updated to " + counter);
}, [counter])
```

There are more hooks that React offers. It's a good idea to be aware of them.

In the next article, I write about React and will look at expanding further on it.

### References


- [React Quick Start](https://react.dev/learn)
- [Youtube Video by JavaScript Mastery](https://www.youtube.com/watch?v=b9eMGE7QtTk)
- [W3Schools React](https://www.w3schools.com/react/default.asp)

### Sample project

- [Movie Search](https://gitlab.com/vigneshm243/entertainment-tracker-app)