~/nyuma.dev

React in 19 minutes's cover image

React in 19 minutes

A crash course that nobody asked for. Actually, Vibe Coders. Definitely Vibe Coders.

19 mins read

From the history of React, to the Virtual DOM, and everything in between, let's cover it all.

Table of Contents

What is React?

Long, long, ago, in a galaxy far, far, away...Umm, no, that's not right. Let's try again. Before we can understand what React is, we need to understand why it was created in the first place.

The problem

Prior to React, web developers would use JavaScript to manipulate the DOM (Document Object Model) directly. This was a problem, because the DOM is slow. Really slow. And the more elements you have on the page, the slower it gets. This is because every time you make a change to the DOM, the browser has to recalculate the layout of the page, and repaint it. This is a very expensive operation, and can cause performance issues, especially on mobile devices. So, how do we solve this problem?

The solution

In 2013, Facebook began their journey to find a better approach for building user interfaces. They were using Backbone.js, a popular JavaScript library at the time. However, they soon realized that they needed a more efficient and performant solution.

At that point, a small group of developers within Facebook came together to address these challenges. They set out to create a new JavaScript library called React, which would revolutionize the way user interfaces were built. The primary motivation behind this effort was to improve the speed and efficiency of rendering user interfaces on the client-side.

During this time, traditional server-side approaches, such as rendering user interfaces using server-side languages like PHP, posed significant limitations. With each user interaction, the server had to re-render the entire page and send it back to the user. This process was slow and inefficient, resulting in a poor user experience.

To overcome these obstacles, Facebook's developers aimed to shift the rendering process to the client-side. By doing so, the server would only need to send data to the client, and the client could handle the rendering locally. This approach drastically reduced the amount of data transfer and server-side processing, resulting in faster and more responsive user interfaces.

As a result, React was born, providing a modernized solution for building client-side user interfaces. Its innovative approach to rendering, component-based architecture, and virtual DOM significantly improved performance and development efficiency.

Funnily enough, React's emergence coincided with AngularJS (Angular 1) losing popularity due to the announcement of breaking changes in Angular 2. This made the migration from Angular 1 to Angular 2 complex and led many developers to explore alternative options. React, with its simplicity and performance advantages, soon became the preferred choice for many developers and has since experienced tremendous growth in popularity since.

If you're interested in learning more about React's history and evolution, I recommend watching the React.js documentary which provides an in-depth exploration of React's origins and its impact on the development community.

How does React work?

Now that we know what React is, and why it even came to be, let's take a look at how it works. React is a JavaScript library that allows you to build user interfaces using components. Components are reusable pieces of code that can be composed to build user interfaces. They can be as simple as a button, or as complex as an entire page. Components are the building blocks of React, and are what make React's compositional model so popular. Let's take a look at an example of a React component:

1const Button = () => {
2 return <button>Click Me!</button>;
3};

As you can see, this is a very simple component. It's just a button that says "Click Me!". But, it's a component nonetheless. Now, let's take a look at how we can use this component in our app:

1const App = () => {
2 return (
3 <div>
4 <Button />
5 </div>
6 );
7};

Here, we've created a new component called App, and we've used our Button component inside of it. This is how React works. You create components, and then you use them to build your app. It's really that simple.

When components are rendered, they return a piece of HTML called JSX. JSX is a syntax extension to JavaScript that allows you to write HTML inside of JavaScript. The great thing about JSX is that it's just JavaScript, so you can use all of the features of JavaScript inside of it. This makes it really easy to build user interfaces, because you don't have to learn a new language. You can just use JavaScript.

The Virtual DOM

Under the hood, React uses something called the Virtual DOM. The Virtual DOM is a representation of the DOM in memory. It's a JavaScript object that contains all of the elements on the page, and their properties. When you make a change to the DOM, React updates the Virtual DOM, and then compares it to the previous Virtual DOM. If there are any differences, React will update the DOM accordingly utilizing a technique called reconciliation.

Remember those demo components from above? In the virtual DOM, it would look something like this:

1const virtualDom = {
2 type: "div",
3 props: {},
4 children: [
5 {
6 type: "Button",
7 props: {},
8 children: [
9 {
10 type: "button",
11 props: {},
12 children: ["Click Me!"],
13 },
14 ],
15 },
16 ],
17};

As you can see, the virtual DOM is just a JavaScript object that contains all of the elements on the page, and their properties. This is what React uses to update the DOM. It's a very efficient way to update the DOM, because it only updates the elements that have changed, rather than the entire DOM. This makes React very fast, and allows it to build user interfaces that are responsive, and performant.

CreateElement

React uses a function called createElement to create elements. This function takes three arguments: the type of element you want to create, the properties of the element, and the children of the element. Let's take a look at an example:

1const element = React.createElement("div", {}, "Hello World!");

Here, we've created a new element called element. It's a div element with no properties, and it has the text "Hello World!" as its children. This is how React creates elements.

JSX

As we mentioned earlier, JSX is a syntax extension to JavaScript that allows you to write HTML inside of JavaScript. Let's take a look at an example of it in action:

1const element = <div>Hello World!</div>;

This is the same element we created earlier, but this time we're using JSX instead of createElement. As you can see, JSX is a lot easier to read, and it's a lot easier to write. This is why most people prefer to use JSX over createElement when building their apps.

Class Components

Class components are another way to create components in React. They're a lot like regular components, but they have a few extra features that make them more useful for everyday use. Let's take a look at an example:

1class Button extends React.Component {
2 render() {
3 return <button>Click Me!</button>;
4 }
5}

Here, we've created a new class component called Button. It's a lot like our regular component, but it has a few extra features that make it more powerful. Let's take a look at what those features are:

  • State
  • Lifecycle Methods
  • Props

State

State is a way to store data in React. It's a lot like a variable, but baked-in to the component. Here's a simple class component that exemplifies this:

1class Button extends React.Component {
2 constructor(props) {
3 super(props);
4 this.state = {
5 count: 0,
6 };
7 }
8
9 render() {
10 return <button>{this.state.count}</button>;
11 }
12}

Here, we've created a new class component called Button. It has a state property called count, which is set to 0. We can access this state property by using this.state.count. Whenever we update the state, React will automatically update the DOM with the new value. This is how React keeps track of changes in the DOM using the Virtual DOM we talked about earlier.

Lifecycle Methods

Lifecycle methods are methods that are called at certain points in the lifecycle of a component. Think of them as hooks/event handlers that allow you to run code at specific points in the lifecycle of a component.

1class Button extends React.Component {
2 constructor(props) {
3 super(props);
4 this.state = {
5 count: 0,
6 };
7 }
8
9 componentDidMount() {
10 console.log("Component Mounted!");
11 }
12
13 render() {
14 return <button>{this.state.count}</button>;
15 }
16}

Here, we've created the same class component as before, but this time we've added a lifecycle method called componentDidMount. This method is called when the component is mounted to the DOM. We can use this method to do things like fetch data from an API, or set up event listeners.

Props

Props are a way to pass data from one component to another. Since components are just functions, you can pass data to them as arguments. There's a few quirks to props, but they're essential in React's model.

1class App extends React.Component {
2 render() {
3 return <Button text="Click Me!" />;
4 }
5}
6
7class Button extends React.Component {
8 render() {
9 return <button>{this.props.text}</button>;
10 }
11}

Here, we've created a new class component called App. It has a child component called Button. We can pass data from the parent component to the child component by using props. In this case, we're passing the text "Click Me!" to the child component. We can access this data by using this.props.text. Props can be used to pass any type of data from one component to another. Functions, objects, arrays, etc.

Functional Components

Functional components are another way to create components in React. They're a lot like regular class components, but they are a lot simpler. Let's take a look at an example:

1const Button = () => {
2 return <button>Click Me!</button>;
3};

Here, we've created a new functional component called Button. It's a lot like our regular component, but it's a lot simpler. It doesn't have any state, lifecycle methods, or props. It's just a function that returns some JSX. This is how most people prefer to create their components in React, because it's a lot simpler to read and write.

Hooks

Remeber those lifecycle methods we talked about earlier? Well, they're not the only way to do things in React. There's another way called hooks. Hooks are a new feature in React that allow you to do things like fetch data from an API, or set up event listeners without using lifecycle methods. Let's take a look at an example:

1const Button = () => {
2 const [count, setCount] = React.useState(0);
3
4 return <button onClick={() => setCount(count + 1)}>{count}</button>;
5};

Here, we've created a new functional component called Button. It uses the useState hook to keep track of the count. Whenever the button is clicked, the count is incremented by one. The [count, setCount] is called a destructured array. It's a way to access the values returned by the useState hook. The first value is the current value of the state, and the second value is a function that allows you to update the state.

There's a lot more to hooks than this, but this is a good place to start. If you want to learn more about hooks, check out the official documentation on hooks.

Why should you use React?

Now that we know what React is, and how it works, let's take a look at why you should use it. There are a lot of reasons why you should use React, but here are a few of the most important ones:

  • React is popular

React is one of the most popular JavaScript libraries out there. It's used by companies like Meta, Netflix, and Airbnb. If you want to get a job as a web developer, you need to know React.

  • React is fast

By using the Virtual DOM, React is able to update the DOM very quickly. The reconciliation technique allows React to only update the elements that have changed, rather than the entire DOM. This makes React blazing fast.

  • React is easy to learn

By knowing JavaScript, you already know React. There's no need to learn a new language. You can just use JavaScript to build your apps. With this in mind, it's a lot easier to learn React than other JavaScript libraries like Angular or Vue where they have their own syntactic sugar on top of JavaScript.

How do you use React?

The React Core team has created a tool called create-react-app that allows you to create a new React app with just one command. Let's take a look at how to use it:

1npx create-react-app my-app

Here, we've created a new React app called my-app. This command will create a new directory called my-app with all of the files needed to get started with React. It will also install all of the dependencies needed to run the app.

Once the app has been created, you can run it by using the following command:

1cd my-app
2npm start

This will start the development server on localhost:3000. You can now open your browser and go to localhost:3000 to see your app running.

However, the create-react-app tool is not the only way to create a React app. There are many other ways to create a React app, but this is the easiest way to get started. The reason we even use create-react-app is that it uses webpack under the hood to bundle all of our JavaScript files into one file. This makes it a lot easier to get started with React, because you don't have to worry about setting up webpack yourself.

Other popular ways to create a React app include:

Here's the getting started steps for Vite:

1npm create vite@latest
1cd my-app
2npm install
3npm run dev

Similar, but Vite runs on port 5173 by default. Additionally, Vite uses esbuild to bundle the JavaScript files, which is a lot faster than webpack.

Learn By Doing: Building a React App

Now that we know what React is, and how it works, let's take a look at how to build a simple React app. For this section, we're going to build a app that allows you to view cat photos in a gallery. Let's get started!

Step 1: Create a new React app

The first thing we need to do is create a new React app. We're going to use the create-react-app tool to do this. Let's take a look at how to do that:

1npx create-react-app photo-gallery
2cd photo-gallery
3npm start

Now that we have the development server running, head over to App.js and delete all of the code in there. We're going to start from scratch.

When making React apps, I like to start from the bottom up. This means that I start with the smallest component, and then work my way up to the largest component. In my opinion, this is the best way to build React apps, because it allows you to focus on one thing at a time, rather than trying to do everything at once.

Step 2: Create PhotoCard component

The first thing we need to do is create our first component. We're going to call this component PhotoCard. Let's take a look at how to do that:

1import React from "react";
2import PropTypes from "prop-types";
3
4const PhotoCard = ({ title, url }) => {
5 return (
6 <div>
7 <h2>{title}</h2>
8 <img src={url} alt={title} />
9 </div>
10 );
11};
12
13PhotoCard.propTypes = {
14 title: PropTypes.string.isRequired,
15 url: PropTypes.string.isRequired,
16};
17
18export default PhotoCard;

Here, we've created a new component called PhotoCard. It takes two props: title and url. We can access these props by using props.title and props.url (or destructuring, like seen above). We're going to use these props to display the title and the image of the photo card. The PropTypes library is used to validate the props that are passed to the component. This is a requirement in React, but generally speaking, you should always validate the props that are passed to your components in order to prevent bugs.

We want to create a gallery of photo cards, so we need to create a new component for each photo card. What we're going to do is create a new component called PhotoGallery that will render a list of photo cards and make that easier. Let's take a look at how to do that:

1import React from "react";
2import PhotoCard from "./PhotoCard";
3
4const getCatPhotos = () => {
5 const promises = [];
6 for (let i = 0; i < 10; i++) {
7 promises.push(
8 fetch("https://api.thecatapi.com/v1/images/search")
9 .then((res) => res.json())
10 .then((data) => data[0])
11 );
12 }
13 return Promise.all(promises);
14};
15
16const PhotoGallery = () => {
17 const [photos, setPhotos] = React.useState([]);
18
19 React.useEffect(() => {
20 getCatPhotos().then((photos) => setPhotos(photos));
21 }, []);
22
23 return (
24 <div>
25 {photos.map((photo) => (
26 <PhotoCard key={photo.id} title={photo.title} url={photo.url} />
27 ))}
28 </div>
29 );
30};

Yeah, I know, that's a lot of code. Let's break it down. First, we're importing the PhotoCard component from the PhotoCard.js file. Then, we're creating a function called getCatPhotos that will fetch 10 random cat photos from the Cat API. We're using the built-in fetch function to do this. The fetch function returns a promise, so we need to use the then method to get the data from the promise. We're also using the Promise.all method to wait for all of the promises to resolve before returning the data. This is a very common pattern in React, so it's important to understand how it's being applied here.

After we've fetched the photos, we're using the useEffect hook to set the state of the photos variable to the photos we fetched. The useEffect hook is a way to run code after the component has been rendered. We're using it here to fetch the photos after the component has been rendered and set the state of the photos variable to the photos we fetched. Once the state has been set, React will automatically update the DOM with the new data.

Finally, we're rendering a list of photo cards using the map method. The map method is a way to iterate over an array and return a new array. We're using it here to render a list of photo cards. We're also using the key prop to give each photo card a unique key. Generally speaking, you should always give each element in a list a "unique" key to prevent bugs.

Step 3: Create PhotoGallery component

Now that we have a component that renders a list of photo cards, we need to create a component that will render the photo gallery. We're going to call this component Main. Let's take a look at how to do that:

1import React from "react";
2import PhotoGallery from "./PhotoGallery";
3
4const Main = () => {
5 return (
6 <div>
7 <h1>Photo Gallery</h1>
8 <PhotoGallery />
9 </div>
10 );
11};
12
13export default Main;

That's it! We've created a new component called Main that renders the photo gallery. We're going to use this component in our App component. Let's take a look at how to do that:

1import React from "react";
2import Main from "./Main";
3
4const App = () => {
5 return (
6 <div>
7 <Main />
8 </div>
9 );
10};
11
12export default App;

Now that we have our App component, we can render it in our index.js file. Let's take a look at how to do that:

1import React from "react";
2import ReactDOM from "react-dom";
3import App from "./App";
4
5ReactDOM.render(React.createElement(App), document.getElementById("root"));
6// or ReactDOM.render(<App />, document.getElementById("root"));

React uses the ReactDOM.render method to render the App component to the DOM. We're using the document.getElementById method to get the root element from the DOM. This is where we want to render our app. We're also using the React.createElement method to create the App component. This is a requirement in React, but generally speaking, you should always use JSX instead of React.createElement.

Now that we've created our app, let's take a look at what it looks like in the browser:

Cat Gallery

As you can see, we've successfully created a photo gallery using React! It's not the prettiest photo gallery in the world, but the goal of this article was to teach you how to build a React app, not how to build a beautiful photo gallery.

Full Code:
1import React from "react";
2import PropTypes from "prop-types";
3
4PhotoCard.propTypes = {
5 title: PropTypes.string.isRequired,
6 url: PropTypes.string.isRequired,
7};
8
9const PhotoCard = ({ title, url }) => {
10 return (
11 <div>
12 <h2>{title}</h2>
13 <img src={url} alt={title} />
14 </div>
15 );
16};
17
18const getCatPhotos = () => {
19 const promises = [];
20 for (let i = 0; i < 10; i++) {
21 promises.push(
22 fetch("https://api.thecatapi.com/v1/images/search")
23 .then((res) => res.json())
24 .then((data) => data[0])
25 );
26 }
27 return Promise.all(promises);
28};
29
30const PhotoGallery = () => {
31 const [photos, setPhotos] = React.useState([]);
32
33 React.useEffect(() => {
34 getCatPhotos().then((photos) => setPhotos(photos));
35 }, []);
36
37 return (
38 <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)" }}>
39 {photos.map((photo) => (
40 <PhotoCard key={photo.id} title={photo.title} url={photo.url} />
41 ))}
42 </div>
43 );
44};
45
46function App() {
47 return (
48 <div>
49 <PhotoGallery />
50 </div>
51 );
52}
53
54export default App;

React has been my favorite JavaScript library for a long time now, and I hope that this ramble has helped you understand why. User interfaces are a huge part of our lives, and React makes that so much easier.

I hope you've enjoyed this and maybe even learned something new. If you have any questions, feel free to reach out to me on Discord @nyumat. I'm always happy to chat!