September 10, 2024
React is officially the most loved frontend library. It's one of the most used frontend libraries and has a great ecosystem and community supporting it.
Although it’s easy to write a hello world, as soon as you want to create a real project you find yourself facing a lot of technical jargon, like rendering, effects, state, memoization etc..
So today I want to explain to you all the terms that React devs use.
I’m gonna start with simple terms like jsx, Components, State and build upon it to explain more complex things like rerendering, memoization, reconciliation. Understand the magic behind react.
Components
The core concept in React is components.
A component is simply a reusable part of the UI.
It can be as small as a button or represent bigger parts, like a whole page.
In fact, everything in React is a component: A typical app will have a Root
component (often called App) which includes TopBar
, Content
and Footer
components.
Inside the TopBar you will have a logo component, some link components and so on…
So how do you define a component?
You can use basic elements like <h1>
, <p>
, etc., but the real power of React is in writing your own components.
You can create a component by defining a function. Staying with our simple example:
function HelloWorldTitle() { return <h1>Hello, world!</h1>; }
Now that you have defined your component, you need to render it in the browser, so that the user can actually see it.
For that, you call the method ReactDOM.render
, which takes the target HTML element where you want your app to be rendered and your component as arguments and displays it. (Note: ReactDOM.render
is largely being replaced by the newer createRoot
API in modern React, but the core concept remains).
Now the elephant in the room, is this weird syntax, that looks like a Frankenstein of JavaScript and HTML. But don’t worry, it’s actually simple.
JSX
JSX is a syntax extension for JavaScript that lets you write HTML-like markup inside a JavaScript file. It might look like you're mixing HTML and JavaScript, but under the hood, JSX is transformed into regular JavaScript.
https://legacy.reactjs.org/docs/introducing-jsx.html#jsx-represents-objects
So, when you write this JSX code:
<h1>Hello, world!</h1>
it gets compiled (by Babel, typically) into this JavaScript code:
const element = React.createElement("h1", null, "Hello, world!");
Or, if you have attributes:
<a href="https://www.example.com">Link</a>
becomes:
const element = React.createElement( "a", { href: "https://www.example.com" }, "Link", );
And for more complex structures:
<div> <h1>Welcome</h1> <p>This is some text.</p> </div>
becomes something like:
const element = React.createElement( "div", null, React.createElement("h1", null, "Welcome"), React.createElement("p", null, "This is some text."), );
As you can see, JSX makes it much easier to write and understand complex UI structures compared to writing the equivalent React.createElement
calls directly. It allows you to express your UI in a way that's closer to HTML, which is often more intuitive. While it's important to understand what's happening behind the scenes, you'll almost always work directly with JSX.
Props
Props, short for properties, are parameters used to configure components. They are how you pass data down from a parent component to a child component. Think of them like arguments to a function.
function SocialMediaCard(props) { return ( <div> <img src={props.profilePicture} alt={props.username + "'s profile picture"} /> <h3>{props.username}</h3> <p>{props.message}</p> <p>Comments: {props.commentCount}</p> </div> ); } // Using the component: <SocialMediaCard username="JohnDoe" message="Just had the best coffee ever!" commentCount={5} profilePicture="/images/profile.jpg" />;
In this example, username
, message
, and commentCount
are props passed to the SocialMediaCard
component. The component then uses these props to display the correct information. Props are immutable (they cannot be changed by the component that receives them).
State
State is how a component manages its own data that can change over time. Unlike props, which are passed down, state is managed within the component. When state changes, the component re-renders.
import React, { useState } from "react"; function LikeButton() { const [liked, setLiked] = useState(false); // Initialize state to false const handleClick = () => { setLiked(!liked); // Toggle the liked state }; return <button onClick={handleClick}>{liked ? "Unlike" : "Like"}</button>; }
Here, useState
is a React Hook (more on hooks later!) that lets us manage state. liked
is the current state value, and setLiked
is a function to update the state. When setLiked
is called, the component re-renders to reflect the new state.
Rerender
When a component's props or state change, React automatically re-renders that component. This means React updates the UI to reflect the new data. This is a core concept in how React keeps the UI in sync with the underlying data.
Virtual DOM
React uses a virtual DOM (Document Object Model). This is a lightweight in-memory representation of the actual DOM. When a component re-renders, React updates the virtual DOM first.
Reconciliation
React then compares the previous virtual DOM with the updated virtual DOM. This process is called reconciliation. React identifies the specific changes that need to be made to the real DOM, and only updates those parts. This makes updates very efficient.
Keys
When rendering lists of items, React needs to be able to identify each item uniquely. This is done using keys
. Keys should be unique within the list. They help React optimize rendering and prevent unexpected behavior.
const items = [ { id: 1, name: "Apple" }, { id: 2, name: "Banana" }, ]; <ul> {items.map((item) => ( <li key={item.id}>{item.name}</li> // Key is crucial here ))} </ul>;
Memoization
Memoization is a technique for optimizing performance by caching the results of expensive function calls. In React, useMemo
and React.memo
are used for memoizing components and calculations, preventing unnecessary re-renders.
Arrow functions
Arrow functions are a concise way to define functions in JavaScript. They are often used in React components, especially with event handlers.
const handleClick = () => { /* ... */ };
Context
Context provides a way to share data deep within the component tree without having to pass props down manually at each level. It's useful for things like themes, user authentication, or locale settings.
Routing
Routing is how you navigate between different pages or views in a web application. React Router is a popular library for handling routing in React apps.
State management
For larger applications, managing state can become complex. State management libraries like Redux or Context API help you organize and manage application state more efficiently.
Error boundaries
Error boundaries are components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of crashing the whole app.
Server components
Server Components are a new feature in React that allows you to render components on the server. This can improve performance by reducing the amount of JavaScript that needs to be sent to the client. This is a more advanced topic and is still evolving.
This should give you a solid foundation for understanding the core concepts of React. Don't be afraid to dive deeper into each of these topics as you continue learning! Happy coding!