Free Programming learning guide
React JS for Beginners: The Complete Learning Roadmap
React JS for Beginners: The Complete Learning Roadmap — a free beginner-level guide covering how to learn react js for beginners. Learn with clear...
What you will learn
- Introduction to React and Environment Setup
- JSX and Component Basics
- Props and Component Composition
- State and Interactivity
- Handling Events and Forms
- Conditional Rendering and Lists
- Side Effects and Data Fetching
- Routing with React Router
- Context API for State Management
- Building and Deploying a React Application
1. Introduction to React and Environment Setup
What Is React and Why Does It Exist? Think about the last time you used a web application like Google Maps, Facebook, or an online shopping cart. You likely clicked a button, and a small piece of the screen updated instantly—perhaps a sidebar slid open or a new item appeared in your cart—without the entire web page going blank and reloading. This seamless, app-like experience is what users expect today. Historically, building these highly interactive websites with plain JavaScript was tedious and error-prone. Developers had to manually track what the web page looked like, figure out exactly what changed, and write instructions to update the browser. As applications grew larger, this manual updating process became a tangled mess. React is a JavaScript library created by Facebook (now Meta) to solve this exact problem. Instead of making you manually update the browser, React introduces a different approach: you tell React what the screen should look like, and React figures out how to update it for you. The Virtual DOM: React’s Secret Sauce To understand why React is so fast, we need to understand the DOM, or Document Object Model. The DOM is essentially the browser's internal blueprint of your web page. When a browser loads an HTML file, it builds a tree-like structure of all the elements (like buttons, text, and images) on the screen. In the early days of the web, interacting with the DOM was slow. If you changed a single piece of text on a massive web page, the browser sometimes had to recalculate the layout of the entire page, causing a visible lag. To fix this, React uses something called the Virtual DOM. The Virtual DOM is exactly what it sounds like: a lightweight, in-memory representation of the actual DOM. Think of it like a rough sketch of your web page that React keeps in its memory. Here is how it works in practice: 1. When your application starts, React creates a Virtual DOM blueprint of your web page and renders it to the real DOM. 2. When something changes (like a user clicking a button to add an item to a cart), React creates a new Virtual DOM blueprint of what the page should look like now. 3. React compares this new blueprint to the old blueprint. This comparison process is called diffing. 4. Once React spots the exact differences between the old and new blueprints, it updates only those specific parts on the real DOM. This targeted updating is called reconciliation. By skipping the heavy lifting of redrawing the entire page, React keeps your application feeling instantaneous, even as it grows in complexity. Real-World Example: A Live Stock Ticker Imagine you are building a financial …
2. JSX and Component Basics
The Problem JSX Solves In the traditional web development workflow, keeping your user interface updated meant manually finding elements in the DOM using JavaScript and instructing the browser to change them. If a user clicked a button and you needed to update a counter, you had to write code that specifically targeted that counter element, calculated the new number, and overwrote the old text. As applications grow, this manual manipulation becomes tedious and error-prone. React takes a different approach. Instead of manually updating the DOM, you tell React what the screen should look like at any given moment, and React's diffing and reconciliation process handles the actual DOM updates. But how exactly do you "tell" React what the screen should look like? You need a way to describe user interfaces—buttons, paragraphs, lists, and forms—using JavaScript. You could write plain JavaScript objects to describe these elements, but doing so is incredibly verbose and hard to read. This is where JSX comes in. What is JSX? JSX stands for JavaScript XML. It is a syntax extension for JavaScript that allows you to write HTML-like markup directly inside your JavaScript files. To understand why JSX is so powerful, look at how you would create a simple heading element in standard JavaScript using React's underlying API: This code creates an <h1 element with a class of "title" and the text "Welcome to my app". It works perfectly, but imagine building an entire webpage this way. A complex navigation bar or a multi-column grid would require dozens of nested React.createElement calls. It would look like a mess of functions and strings. JSX allows you to write that exact same structure in a way that looks exactly like HTML: This is much easier to read and write. However, it is crucial to remember a fundamental fact: JSX is not valid JavaScript. Your web browser cannot read it. How JSX Compiles to Regular JavaScript Because browsers only understand standard JavaScript, JSX must be translated—or compiled—into regular JavaScript before it reaches the browser. In Chapter 1, we used Vite to set up our React project. Vite handles this compilation process behind the scenes using a tool called Babel. Every time you save a file, Vite instantly translates your JSX into standard React.createElement() calls. When you write: The compiler translates it into: JSX is essentially just a friendlier disguise for standard JavaScript. You write the HTML-like syntax, and the compiler does the heavy lifting of converting it into the JavaScript objects that React uses to build the Virtual DOM. Rules of Writing Valid JSX Because JSX is a blend of HTML and JavaScript, it has a few specific rules you must follow. While it looks like HTML, it behaves …
3. Props and Component Composition
The Problem with Hardcoded Components Imagine you are building an online bookstore. On the homepage, you want to display a list of bestselling books. Each book needs a cover image, a title, an author name, and a price. If you followed the patterns from the previous chapter on JSX and Component Basics, your first instinct might be to build a <Book / component. But if that component can only display one specific book—say, The Great Gatsby by F. Scott Fitzgerald for $12.99—you would have to write a completely new component for every single book in your store. This defeats the purpose of using React. We want to write a component once and reuse it infinitely. To do that, our component needs to be a blank template, waiting for specific data to be handed to it before it renders. This is where props come in. What Are Props? Props (short for "properties") are the mechanism React uses to pass data from a parent component down to a child component. Think of a component as a blank form. The props are the instructions and details you fill into the form before handing it to someone else. If a component is a function, props are the arguments you pass into that function to change its output. Props are always passed in a single direction: from parent to child. This is known as unidirectional data flow. A parent can hand data down to a child, but a child cannot directly send data back up to the parent, nor can a child change the data it receives from the parent. To a child component, props are read-only. If the child needs new data, the parent must pass down different props. Passing Data to a Component In JSX, passing props looks exactly like assigning attributes to an HTML tag. You write the name of the prop, an equals sign, and the value you want to pass. Let’s rewrite our hardcoded book component to accept props instead. Notice that the function now accepts a parameter called props. In React, props is always a JavaScript object. Inside the component, we access our data using dot notation (props.title, props.author, etc.) and inject it into our JSX using curly braces. Now, let's look at the parent component that uses our Book component. Now we have a reusable Book component. The parent (Bookstore) defines the data and passes it down. If we want to add a new book to the page, we just add another <Book / tag with different attributes. Passing Different Data Types In the example above, we passed strings. By default, if you write title="The Great Gatsby", React treats the value as a string. But what if you …
4. State and Interactivity
The Missing Ingredient: Why Static Components Aren't Enough Imagine you are building a simple counter application. You want a button on the screen that, when clicked, increases a number by one. If you only had the tools from the previous chapters—JSX, Components, and Props—you would quickly run into a wall. You could create a Counter component and pass it a prop called initialCount set to 0. But how do you change that number when the user clicks the button? Props are strictly read-only. A component cannot modify the props passed down to it by its parent. If the component could magically change its own props, the data flow would become chaotic and impossible to trace. To make our applications feel alive and responsive to user actions, we need a way for a component to "remember" things over time and trigger updates to the screen. We need a way for a component to hold its own private, changeable data. In React, this private memory is called state. What is State? State vs. Props State is the internal data managed by a component. It represents the current condition or "memory" of that specific component. Unlike props, which are passed down from parent to child like hand-me-down clothes, state is created and maintained entirely within the component itself. To understand the difference clearly, think of a car: Props are like the car's color, model, and number of doors. These attributes are determined when the car is built (by the parent) and don't change during the drive. State is like the car's current speed, the radio station currently playing, or the amount of fuel in the tank. These are internal conditions that change over time while the car is operating. Here is a quick breakdown of the key differences: Origin: Props come from outside the component (passed by the parent). State is created inside the component. Mutability: Props are immutable (read-only). State is mutable (changeable). Triggering Updates: When a component's props change, the parent component triggers the update. When a component's state changes, the component itself triggers the update. Scope: Props are how components talk to their children. State is how a component manages its own internal logic. When a component's state changes, React performs a process called reconciliation. React creates a new version of the Virtual DOM, compares it to the previous version using a process called diffing, and then updates the actual DOM only where necessary. This is how React keeps the screen perfectly synced with your data. The useState Hook: Your Component's Memory To give a component its own state, we use a special built-in function called a Hook. A Hook is simply a React function that "hooks into" React's internal …
5. Handling Events and Forms
Listening to the User: React Event Handlers Think about the last time you used a web application. You typed a search query into a box, clicked a "Submit" button, or toggled a dark mode switch. Every time you do one of those things, the application is listening for a specific action and responding to it. In web development, these actions are called events, and the code that runs in response is called an event handler. In traditional web development, you might write code that searches the document for a specific HTML element and attaches an event listener to it. In React, things are much more direct. Because you are already writing your UI using JSX, you can attach event handlers directly to the JSX elements right where you define them. React events are named using camelCase. For example, instead of the standard HTML onclick attribute, you will use onClick. Instead of onchange, you will use onChange. The onClick Handler Let’s look at the most straightforward event: a user clicking a button. To respond to this, you pass a JavaScript function to the onClick attribute on a <button element. Here is a simple example where clicking a button logs a message to the console: Notice a crucial detail here: onClick={handleClick}. We are passing the function itself, not calling it. If you were to write onClick={handleClick()}, the function would execute the exact moment the component renders, rather than waiting for the click. By passing the function reference, you are telling React, "When this button is clicked, run this function." The onChange Handler While clicking buttons is useful, the most common event you will handle in forms is typing into a text box. When a user types, the value of the input changes. React listens for this using the onChange event. Let's look at an example where we capture what the user types and display it back to them in real time: Understanding the Event Object In the handleTyping function above, you might have noticed we passed a parameter called event. When an event fires in React, it passes an event object to your handler function. This object contains all the details about what just happened. The most common property you will use from this object is event.target. The target represents the exact DOM element that triggered the event. For an <input element, event.target.value gives you the current text inside that input box. Note: React uses a wrapper around the native browser event called SyntheticEvent. It behaves exactly like a regular browser event, but it ensures that your events work identically across all browsers (Chrome, Firefox, Safari, etc.) without you having to write browser-specific code. Controlled Inputs: Making React the Boss In the …
6. Conditional Rendering and Lists
The Need for Dynamic UIs Imagine you are building an online shopping cart. When the cart is empty, you want to display a friendly message saying, "Your cart is empty." But when a customer adds items, that message needs to disappear and be replaced by a list of products. Furthermore, if a user is browsing a clothing store, they might want to see only the items currently on sale. In traditional static HTML, you would have to write out the markup for every possible scenario or write complex JavaScript to manually tear down and rebuild parts of the webpage. In React, we have a much better way. Because React uses JSX—which you learned in Chapter 2 is just a syntax extension of JavaScript—we can use standard JavaScript logic to decide what the browser should display. This is called conditional rendering: the ability to render different UI elements based on certain conditions. Alongside this, we often need to display collections of data. Instead of hardcoding ten separate <div elements for ten products, we can take an array of product data and instruct React to generate the HTML for us. This is called list rendering. Together, these two skills allow you to build highly dynamic, data-driven interfaces. Conditional Rendering with Ternary Operators In Chapter 4, you learned how to use useState to track data that changes over time. Once you have state, you need a way to change the UI when that state updates. The most common and versatile way to conditionally render in React is the ternary operator. The ternary operator is a standard JavaScript feature that acts like a one-line if/else statement. It evaluates a condition and returns one value if the condition is true, and a different value if it is false. The syntax looks like this: condition ? trueResult : falseResult In a React component, you can embed this directly inside your JSX using curly braces {}. Let’s look at a real-world example: a user login screen. In this example, the component receives a prop called isLoggedIn. If it is true, React renders the <Dashboard / component. If it is false, React renders the <LoginForm / component. Because the ternary operator returns a value, it fits perfectly inside JSX. You can also use it to conditionally apply CSS classes or text: Conditional Rendering with Logical AND Sometimes, you don't have an "else" scenario. You only want to render something if a condition is true, and render nothing at all if it is false. While you could use a ternary operator and return null for the false case (condition ? <Component / : null), JavaScript provides a cleaner shortcut: the logical AND operator (&&). In JavaScript, the && operator …
7. Side Effects and Data Fetching
The Missing Piece: Pure Components vs. The Outside World Imagine you are ordering a coffee at your favorite café. If the café operated like a pure React component, the barista would take your order, calculate the exact change, and hand you your coffee. Everything would happen perfectly inside the four walls of the café. But real applications don't live in a vacuum. Before the barista hands you the coffee, they might need to check the back room to see if they have enough beans, or swipe your credit card through an external machine. These actions—reaching outside the café to interact with an external system—are called side effects. Up to this point in our journey, we have built components using JSX, passed data using props, and managed interactivity using state. Everything we have done so far has been "pure." If you give a React component the same state and props, it renders the exact same screen. React's job—looking at the Virtual DOM, diffing changes, and reconciliation with the actual DOM—is entirely focused on figuring out what to draw on the screen. But what happens when a component needs to do something that isn't about drawing on the screen? What is a Side Effect? In React, a side effect is any action a component takes that affects something outside its own scope. A component's primary job is to return JSX. If it does anything else, that "anything else" is a side effect. Common side effects include: Fetching data from an external server or API. Manually changing the DOM (like changing the document title or focusing an input). Setting up a subscription to a WebSocket or a timer using setInterval. Because React controls the rendering process, you cannot reliably perform these side effects directly in the main body of your component. If you try to fetch data right in the middle of your component function, it will pause the render, confuse the diffing algorithm, and likely crash your app. React needs a dedicated space to handle these outside interactions. That space is the useEffect hook. Stepping Outside the Render: The useEffect Hook The useEffect hook is React's way of saying, "Go ahead and render the component first. Once it is drawn on the screen, then I will run this extra function." The name is a combination of "use" (the standard prefix for React hooks) and "Effect" (short for side effect). Here is what a basic useEffect looks like: The Two Phases of useEffect To understand how useEffect works, you need to understand that it splits a component's lifecycle into two distinct phases: 1. The Render Phase: React calls your component function, figures out the JSX, and updates the DOM. 2. The Effect Phase: …
8. Routing with React Router
The Problem with Single-Page Applications Imagine you are browsing an online store. You click on the "Electronics" category, and the page updates to show laptops and phones. You click on a specific laptop, and the page changes again to show the details, price, and an "Add to Cart" button. If you were building this website using traditional web development, every time you clicked a link, your browser would send a request to a server, wait for a completely new HTML page to be generated, and refresh the screen. However, back in Chapter 1, we established that React is used to build Single-Page Applications (SPAs). In an SPA, the browser only loads a single HTML file. When you navigate around the app, React uses the Virtual DOM, diffing, and reconciliation to simply swap out the components on the screen without ever asking the server for a new HTML page. This creates a unique problem: If the browser never actually loads a new HTML page, how does the URL in the address bar change? How can a user use the browser's "Back" button? And how can they bookmark a specific product page to share with a friend? The answer is routing. Routing is the process of keeping the browser URL in sync with what is currently being displayed on the screen. In the React ecosystem, the standard tool for this job is a third-party library called React Router. By the end of this chapter, you will be able to add seamless, multi-page-feeling navigation to your React applications. Installing and Configuring React Router Because React Router is a third-party library, it doesn't come built into React. We need to install it into our project. Open your terminal inside your VS Code editor (or your operating system's terminal, whether you are on Windows or Mac). Ensure you are in the root directory of your React project. Run the following npm command: Note: The package is named react-router-dom because it is specifically designed for web applications (the DOM), as opposed to React Native apps for mobile. The BrowserRouter Component Once installed, React Router needs to be configured. To do this, we need to wrap our entire application in a special component called <BrowserRouter. Think of <BrowserRouter as the conductor of an orchestra. It doesn't make any sound itself, but it listens to the browser's address bar and tells all the other React Router components what the current URL is. In a typical project created with Vite, your src/main.jsx (or src/main.js) file is where your app is attached to the DOM. We will import BrowserRouter and wrap the <App / component with it. By wrapping <App / inside <BrowserRouter, every component in our application now has …
9. Context API for State Management
The Problem with Prop Drilling Imagine you are building the user profile section for a new social media application. At the very top of your component tree, an App component holds the authenticated user's data in its state—perhaps their username, avatar, and email. Down at the bottom of your tree, a deeply nested ProfileHeader component needs to display that username. In the earlier chapters on Props and Component Composition and State and Interactivity, you learned how to pass data down from a parent to a child using props. Following that logic, your component tree might look like this: 1. App (holds user state) 2. Dashboard (layout wrapper) 3. Sidebar (navigation) 4. UserProfile (container for profile info) 5. ProfileHeader (displays the username) To get the username from App to ProfileHeader, you have to pass it as a prop through Dashboard, Sidebar, and UserProfile. The intermediate components (Dashboard, Sidebar, and UserProfile) don't actually care about the user's username. They don't display it, and they don't modify it. They are simply acting as relay stations, passing the data down to the next level. This frustrating phenomenon is known as prop drilling. Prop drilling (sometimes called "threading") occurs when you pass props through multiple levels of components that do not need the data themselves, merely to get the data to a deeply nested child that does. While passing a prop down one or two levels is perfectly fine, prop drilling creates several major problems as your application grows: Tight Coupling: Intermediate components become unnecessarily tied to the data structure of their parents. If you decide to rename the prop from user to currentUser, you have to update it in every component it passes through. Maintenance Nightmares: Adding a new deeply nested component that needs the data means modifying the prop chains in all the components above it. Code Clutter: Your components become littered with props that have nothing to do with their actual purpose, making them harder to read and understand. React provides a built-in solution to bypass the middlemen entirely: the Context API. What is the Context API? The Context API is a built-in React feature that allows you to share data globally across the entire component tree without having to manually pass props down at every level. Think of it like a company bulletin board. If the CEO (the App component) wants to announce a new policy, they don't whisper it to a manager, who whispers it to a supervisor, who eventually tells the employee. Instead, the CEO pins the announcement to a central bulletin board. Any employee (nested component) who needs that information can simply walk up to the bulletin board and read it. To use the Context API, you need …
10. Building and Deploying a React Application
You have spent nine chapters learning how to build a React application. You understand the Virtual DOM, you can compose complex UIs using props, you manage application state, fetch data from APIs, and handle routing. Right now, your application lives entirely on your local machine. You run a command in your terminal, your browser opens to localhost:3000, and you can see your work. But what happens when you want your mother, your friends, or a prospective employer to see your application? They don’t have your computer, your code, or your local server. It is time to take your React application out of your living room and put it on the global stage. This process is known as deployment. Before we can deploy, however, we have to pack our application into a neat, optimized package—a process called building. The Difference Between Development and Production Throughout this book, you have been running your application in development mode (usually by typing npm start or npm run dev in your terminal). Development mode is designed for you, the developer. It includes a lot of behind-the-scenes machinery to make your life easier. For example, when you save a file in VS Code, the browser automatically refreshes. If you make a mistake in your JSX, you get a detailed, friendly error message overlaid on your screen. This is incredibly helpful, but it comes at a cost: it is slow and heavy. The development server has to read, compile, and serve your files on the fly every single time you make a request. Production mode, on the other hand, is designed for your end-users. It strips away all the developer tools and error overlays. It takes your entire application and squashes it down into the smallest, fastest possible version of itself. In production mode, there is no local server reading your files live; instead, you are just serving static, pre-built files to the browser. What Happens During the Build Process? When you write React code, you write it in a way that is easy for humans to understand. You use JSX, you split your code into multiple files, and you might use modern JavaScript features that older browsers don't recognize. The browser, however, doesn't understand JSX, and it doesn't care how neatly you organized your component files. The browser only understands standard HTML, CSS, and vanilla JavaScript. To bridge this gap, we use a bundler. Understanding the Bundler A bundler is a tool that takes your scattered, human-friendly source code and bundles it together into a few browser-friendly files. When you run the build command, the bundler performs several critical tasks: 1. Module Resolution: It looks at your code, finds all the import and export statements (which …
Continue learning
- How to Learn to Code with JavaScript: A Beginner's GuideHow to Learn to Code with JavaScript: A Beginner's Guide — a free beginner-level guide covering how to learn to code with javascript. Learn with clear...
- JavaScript for Beginners: Web Dev GuideJavaScript for Beginners: Web Dev Guide — a free beginner-level guide covering learn javascript for web development. Learn with clear explanations,...
- Mastering React JS for Web DevelopmentMastering React JS for Web Development — a free intermediate-level guide covering learn react js for web development. Learn with clear explanations,...
- TypeScript for JavaScript Developers: A Complete GuideTypeScript for JavaScript Developers: A Complete Guide — a free intermediate-level guide covering learn typescript for javascript developers. Learn...