Every React Concept Explained

Every React Concept Explained

Written by Massa Medi

React is a JavaScript library with a reputation for tossing around fancy terms like reconciliation, composition, and error boundaries. But what do all these terms actually mean? If you've felt lost in the jargon, buckle up: we're going to walk through the essentials of React, from its foundational building blocks to advanced architectural features—no prior experience required.

Let's Start at the Beginning: Components

React applications are built with components—the fundamental units that make up everything visible in your app. Think of components like Lego blocks: you can use them to construct simple items like buttons and inputs, or snap several together to build entire pages. You can reuse components as often as you want, giving your projects versatility and consistency.

Each React component is just a JavaScript function that returns markup. But here's the twist: React components don't return plain HTML. Instead, they use something called JSX—JavaScript syntax that looks like HTML but is actually JavaScript in disguise. JSX makes writing UIs much cleaner and easier to read than using React’s createElement function (which, frankly, gets old very fast).

JSX: JavaScript in a Fake Mustache

JSX, though optional, is nearly universal in React codebases. However, since it's JavaScript, there are some differences from HTML. For example, you must use camelCase for attributes. Instead of writing class in HTML, React requires className. That's because class is a reserved word in JavaScript.

HTML is largely static and unchanging, but React and JSX shine because you can inject dynamic JavaScript values directly into your markup using curly braces ({}). Inside these curly braces, you can use numbers, strings, variables, and even entire functions. This dynamic power lets you display up-to-date values, style elements conditionally, and pass logic straight into your UI.

Every Component Needs a Parent

Since React components are just functions that return a value, each must return one parent element. If you try to return multiple sibling elements at the root, React will throw a big error. Developers often wrap their components in a <div>, but if you don’t want to clutter your DOM, you can use a React Fragment—written as <></>—to group elements without adding extra nodes to the HTML page.

Passing Data: Props and the Magic of Composition

What if you want to pass information into a component? That's where props come in. To define a prop, simply add it as an attribute to your component (<Hello name="Alice" />). Inside your component, props arrive as an object and can be accessed with standard JavaScript syntax: props.name.

Props are like custom attributes you can send to any component—and yes, you can pass anything: strings, numbers, objects, arrays, and even other components. This brings us to the children prop. If you use both opening and closing tags for a component, you can nest other React elements inside. Those become accessible as props.children. This approach fuels Composition, organizing your app’s building blocks in a flexible, powerful way.

The children prop shines for layout components. For instance, you might have a <Card> component that gives its children a consistent style—handy for rendering multiple unique users, posts, or products in a visually uniform way.

The Misunderstood “Key” Prop

There's another built-in prop in React: key. Despite its name, it doesn't unlock secret features! The key prop helps React keep track of elements in lists, improving performance and stability. When mapping over arrays to generate UI—say, a list of to-do items—each element needs a unique key. If you forget, React will remind you (with console warnings). If nothing unique exists, use the current index as a fallback.

Rendering: From Code to Browser

You might be wondering: how does React transform your components into visible content in the browser? This process is called rendering. Under the hood, React uses a clever strategy to make this fast and efficient, leveraging something called the virtual DOM (vdom).

The DOM—short for Document Object Model—is how browsers internally structure all the elements of a web page, typically represented as a tree. React maintains its own virtual DOM in memory. When the state of your app changes, React updates the virtual DOM first, which is much quicker than updating the real DOM. Then, React uses a process calleddiffing to compare the new virtual DOM with the previous version, detecting what changed. Through reconciliation, only those changed parts are updated in the real DOM, giving you speedy, efficient updates.

React Event Handling: Linking Users and Code

Users interact with your app through many different events—clicks, mouse movements, keypresses, and more. Event handling lets you respond to these events. React offers built-in events like onClick,onChange, and onSubmit. For example, you might attach onClick to a button and trigger a function when that button is clicked, such as displaying an alert or updating a counter.

State: The Lifeblood of React Apps

To keep track of data that changes over time (like a photo gallery's current image, the number of “likes,” or the value in an input box), React uses state. But don't confuse this with a “state” on the map! State in React is like a camera snapshot—it represents the app at a specific moment.

You can't just use regular JavaScript variables for state, since updating those won't trigger a re-render. Instead, React gives us hooks like useState and useReducer to manage dynamic values. useState returns a pair—your state variable and a function to update it. Update the state, and React updates your UI. It's as simple as const [likes, setLikes] = useState(0);, then increasing likes each time the user clicks the “like” button.

Controlled Components

Controlled components make use of state to keep form elements in sync. For example, consider a text input: with a controlled component, every keystroke updates state, and the input always reflects that state. Here's what happens:

This pattern ensures your app's UI is predictable and easy to debug: if you need to change the component’s behavior, simply amend the controlling state.

React Hooks: Your Tools for Managing Everything

Hooks are special functions that provide access to React features inside function components. The five main hook types are:

Realistically, you'll use useState, useEffect, and useRef most often in day-to-day projects.

Purity: Keeping React Components Predictable

In programming, “purity” refers to a function always producing the same output given the same input (like a math formula). Pure React components should only render their JSX and never modify variables or objects outside their scope during render. If a component mutates external state while rendering (like incrementing a counter each time it displays), the output can become unreliable, especially when reusing the component.

To help developers write pure components, React provides StrictMode—a wrapper component that highlights risky or unsafe patterns as you develop. Just wrap your app in <StrictMode> and React will alert you to anti-patterns before they break your application.

Working with External Systems: Effects, Side Effects, and useEffect

Sometimes you need to interact with systems outside of React: for example, fetching data from a server or using browser APIs. This is called handling side effects. While many effects are best handled inside event handlers (like Ping! Sending a server request after someone clicks “submit”), some should run during the component’s lifecycle.useEffect is React’s hook for running side effects when components mount, update, or unmount—such as fetching initial data or cleaning up event listeners.

Accessing the Real DOM: useRef and the ref Prop

Occasionally, you need to work with the actual DOM—directly focusing an input, measuring an element’s size, or integrating with third-party UI libraries. In those cases, useRef lets you create a reference object, and the ref attribute attaches it to a React element. Unlike state, updating a ref does not cause a re-render. This approach is often easier and more robust than trying to force React to handle everything indirectly.

Sharing Data Across Components: Context

As React apps grow, you’ll likely have deeply nested components that require access to shared data (think user info, themes, or language settings). Passing props down multiple levels gets unwieldy. Enter Context: a built-in feature that lets you share values throughout your component tree—without manual prop drilling.

To use context, you:

  1. Create a context object in a parent component.
  2. Wrap the target subtree in a Context.Provider and specify the value to share.
  3. In any nested child, call useContext to access the shared value directly, no matter how deep it sits in the tree.

This powerful pattern drastically reduces complexity in large apps.

Portals: Breaking Out of the DOM Hierarchy

Sometimes, you want a React component to appear elsewhere in the HTML structure—outside its parent container. Enter Portals. Portals allow you to render children into any DOM node you choose. This is invaluable for UI elements like modals, dropdown menus, or tooltips, which might otherwise get visually trapped by their parent’s styles.

To create a Portal, use the createPortal function. Pass in your component and the DOM node where it should appear—a modal dialog, for example, layered over the entire page.

Suspense: Handling Loading States Gracefully

Suspense is a React feature that improves the user experience by showing fallback content (like a spinner or custom message) while a component or its data is loading. Simply wrap the slow-loading component in a <Suspense> component and provide fallback content. This pattern also makes lazy loading components straightforward, helping apps feel snappy even when working with large bundles or network delays.

Error Boundaries: Keeping Your App Resilient

Even the best apps encounter errors, and in React, rendering errors can bring down your entire UI. Error boundaries are specially designed components that catch rendering errors in their subtree and display fallback UI, preventing a total crash.

For example, suppose a certain component throws an error if a user isn’t defined. By wrapping this section in an Error Boundary, you can display a custom message (such as “Oops, something went wrong!”) instead of a blank screen or error dump.

Ready to Go Deeper?

React is a vast library with endless possibilities. If you’re eager to master these concepts and more, check out the full bootcamp at reactbootcamp.dev. Whether you’re just starting or refining your skills, there’s plenty to learn and explore.

We hope you learned a lot in this guide—see you in the next one!

Recommended Articles

Code Report