React is a declarative, component-based, open-source front-end JavaScript library for building user interfaces. Whew! There’s a lot to unpack there, so let’s go through each piece of that definition.
What Is React Used For?
Declarative
There are two paradigms in programming we often hear about: declarative and imperative. Imperative programming is writing the actual steps for how something should behave, whereas declarative just expresses how something should behave without the programmer needing to specify the individual steps.
Consider these two pieces of code. In the first, we can see that we have to specify each step to create the HTML we want.
export const addHeading = () => {
// create the heading
const heading = document.createElement('h2')
// fill it with the text we want
heading.textContent = 'Hello, world';
// add the style we want
heading.style.color = "pink"
// add it to the page
document.body.appendChild(heading)
}
In the second, we have a React component (we’ll get into this more later) and it accomplishes much the same thing without having to explicitly write out each step. We can just tell React what our HTML should look like and it’ll go ahead and create that.
export const Heading = () => {
return <h1 style={{ color: "pink" }}>Hello, world!</h1>;
};
Component-Based
A component is a combination of HTML and (sometimes) JavaScript code that encapsulates some specific part of the user interface (UI). Some of the main benefits of this component-based approach are reusability and composability. All web pages have some repeated elements. React allows you to make that component once, then reuse it in different scenarios.
For example, if we’re recreating Jeni’s ice cream flavors page using React, we can consider each of the highlighted color areas a separate component we could build once and reuse (there are likely many more on the page that aren’t highlighted).
Components use data passed into them in order to render additional content in different scenarios, and are often composed of multiple components themselves. We can see an example of that with the ice cream card component (highlighted in pink), which has a plus sign button component inside it (highlighted in blue).
Open Source
Meta (formerly Facebook) wrote and continues to maintain React. That said, all the React code is available in their public GitHub repository. Anybody can contribute to the React project by opening a pull request. Your request has to be approved by the maintainers of course, but this open-source approach means there’s an engaged community around improving React and keeping it high quality.
Front-End JavaScript Library
Even though React’s own website describes itself as a library, there’s a surprising amount of debate about whether React is a library or in fact a framework. In broad terms, a framework is opinionated and dictates architectural code decisions, whereas a library provides tools that can be plugged into existing code. While React does provide a create-react-app
command which scaffolds a whole application including build tools, the idea is that React doesn’t necessarily dictate structure or tooling. In fact, there are softwares such as Next.js and Gatsby that build upon React to create an architecturally rigid framework. Even still, you might see React grouped into lists of front-end frameworks.
Building User Interfaces
Developers use React to build user-facing web pages and often favor it for how fast and responsive apps can be while using its tools.
How Does React Work?
We’ve talked a few times about how fast React can be. The majority of the magic is in what’s called the Virtual DOM (document object model). The regular, non-virtual DOM is a representation of an HTML document in a tree structure where each element is a node that you can manipulate programmatically.
Manipulating the DOM directly can be quite costly. To change a node, you must first locate it by traversing the tree, then update and re-render the node. If there happen to be many changes, this can create performance issues and bottlenecks.
This is where the Virtual DOM comes into play. As we saw in the explanation of declarative programming above, React takes away the need to write code that directly manipulates the DOM. Instead, React creates a copy of the actual DOM. Any change to the HTML that should happen due to some change in data first creates another copy of the Virtual DOM. React then compares the new copy with the old and batches only the needed updates to the real DOM.
Due to the powerful diffing algorithms that React employs, it’s possible to see frequent DOM manipulations and re-rendering without performance suffering.
How to Use React
React created a syntax for writing HTML with Javascript called JSX. We can use it to compose components into a hierarchy that represents the display we want.
Let’s look at the Jeni’s page again.
If we were to represent this (loosely) with a React component tree, it might look something like this:
App is the most top level component that acts as a container for the rest of the components. Next are Navbar
and MainContent
as siblings. Navbar
renders those three little icons in the top right of the page. MainContent
renders ice cream cards, which in turn each render a special button.
Let’s look at how we could write this in code without really focusing on the syntax or worrying about specifics. We see that the App
component renders the two siblings (Navbar
and MainContent
), then each of those renders the children for which they are responsible. A great example of the reusability of components happens inside the MainContent
component. We see that for each ice cream, we can use the same IceCreamCard
component. We will pass in slightly different information, but the component itself gets reused for each new ice cream.
Note how in the IceCreamCard
component, we’re actually using plain HTML elements in addition to some custom components. Often, the farther down the tree you go, the more HTML you’ll see as we still use it to create the actual structure of the app we’re building, almost like legos.
const App = () => {
return (
<>
<Navbar />
<MainContent />
</>
);
};
export const Navbar = () => {
const icons = []// some array of icons
return (
{icons.map(icon => <Icon />)}
)
}
export const MainContent = () => {
const iceCreamList = [] // some array of ice creams
return (
{iceCreamList.map(iceCream => (
<IceCreamCard image={iceCream.image} title={iceCream.title} />
))
}
)
}
export const IceCreamCard = ({image, title}) => {
return (
<div>
<img src={image} alt={title}/>
<AddToCartButton />
</div>
)
}
React Disadvantages
We’ve seen how powerful and developer friendly React can be, however there’s no such thing as a perfect solution. React does have some drawbacks as well.
- Flexibility (maybe too much?): The same boon we talked about that allows a developer to create the architecture they would like can also cause a longer development cycle and more opportunities for mistakes as there are more moving parts.
- Documentation: Even though the React community is great, the actual React documentation is quite outdated and not the best source for current best practices.
- Learning curve: Between JSX and the intricacies of React’s render cycle, learning React can have a steep learning curve.
Alternatives to React
One simple alternative to using React is to use a framework that’s built upon React such as Next.js or Gatsby. They offer all the power of React with a more opinionated structure (reducing the hard work of figuring that out for yourself) and some additional functionality included.
The other popular options are Vue, Svelte and Angular (in that order). They each have their own minor advantages and disadvantages, but React still reigns supreme.