React: Library or Framework? Or something else....
Kevin Sullivan
Posted on December 14, 2019
Have you ever heard someone say this,
React isn't a framework, it's a library
I have.
So, which camp do you fall in? Is it a library? Is it a framework?
Background
I was tasked not too long ago with creating a React Native app (whatever that is...). After developing for a while, I couldn't help but get the feeling that an app framework should do more than React Native was doing. It just didn't feel like a framework. So, maybe I wasn't building a React Native app. Maybe I was building a React app, and using React Native as more of a component library.
After a little while longer, I started getting a similar feeling but for React. The Redux code I was writing seemed more like application stuff, so maybe I was building a Redux app. But then what was I using React for?
...ummm
...errr
...well
I wasn't sure what.
After longer still, I realized Redux was good at encapsulating business logic, but it too didn't feel like an application framework. Maybe I was building a javascript app and using all that other stuff cobbled together to make a framework? Maybe....?
So to better clarify these thoughts, I made an app. It's a simple app. TicTacToe. Here is is, just so you believe me.
Then, I looked at all the places where I used React to see if I could figure out what I was using it for. If it's used for "fundamental stuff" that shapes the app, then it must be a framework, right?
import * as React from 'react'
Let's take a look at one example of using React
// Display.tsx
import * as React from "react";
import { TicTacToeContext } from "../../connect";
import { Col } from "../../../utils";
interface Props {}
interface State {
display: boolean;
}
export class Display extends React.Component<Props, State> {
static contextType = TicTacToeContext;
context: React.ContextType<typeof TicTacToeContext>;
state = {
display: true
};
render() {
const { gameOver, currentPlayerId, winnerId, tied, newGame } = this.context;
const { display } = this.state;
return (
<>
{display ? (
<button onClick={() => this.setState({ display: false })}>
Hide
</button>
) : (
<button onClick={() => this.setState({ display: true })}>Show</button>
)}
{display && (
<Col>
{!gameOver && `Current Player: ${currentPlayerId}`}
{gameOver && (
<>
{winnerId && `${winnerId} Won!`}
{tied && "Tied!"}
<button onClick={newGame}>New Game?</button>
</>
)}
</Col>
)}
</>
);
}
}
It's a pretty harmless component definition. And it depends on React for a few things. Let's see what we are actually using it for.
React.Component
This component is written using the older (no longer recommended) class syntax. But we could just as easily write this using the "newer" syntax (good old javascript functions). And seeing how classes are kinda like syntactic sugar for functions anyway, let's drop one use of React, and re-write it like this:
export const Display: React.FC = () => {
const [display, setDisplay] = React.useState(true);
const {
gameOver,
currentPlayerId,
winnerId,
tied,
newGame
} = React.useContext(TicTacToeContext);
return (
<>
{display ? (
<button onClick={() => setDisplay(false)}>Hide</button>
) : (
<button onClick={() => setDisplay(true)}>Show</button>
)}
{display && (
<Col>
{!gameOver && `Current Player: ${currentPlayerId}`}
{gameOver && (
<>
{winnerId && `${winnerId} Won!`}
{tied && "Tied!"}
<button onClick={newGame}>New Game?</button>
</>
)}
</Col>
)}
</>
);
};
Types
It looks like we traded one use of React for several more...
export const Display: React.FC = () => { ... }
So, this application is created with typescript, which is then compiled to javascript. React exports some types to help us write typescript. But these types are for the developer, and not for app functionality. We could remove these and the application would still run just fine.
JSX
Even if we were to eliminate every explicit use of React in this component, there would still be one more implicit use: JSX.
Basically, JSX is a syntactic sugar that is meant to be compiled into valid javascript. Well, what does it get de-sugared to?
I'm glad you asked
This:
const element = <h1 className="greeting">Hello, world!</h1>;
Becomes this:
const element = React.createElement(
"h1",
{ className: "greeting" },
"Hello, world!"
);
But these function calls get evaluated to (roughly) this:
const element = {
type: "h1",
props: {
className: "greeting",
children: "Hello, world!"
}
};
So, React in this capacity, is syntactic sugar and helper functions. We could go so far as to replace all of the JSX in Display.tsx
with the objects that they would evaluate to, and eliminate one more use of react
.
You can read more about this here
And mess around with a little demo here
Context
I see that this component uses context. That seems kinda significant. So, what's that all about?
React.createContext
doesn't do anything all that special. Much like the React.createElement
used in JSX, it's a function to help create a plain old javascript object.
From a blog post by Dan Abramov,
// A bit simplified
function createContext(defaultValue) {
let context = {
_currentValue: defaultValue,
Provider: null,
Consumer: null
};
context.Provider = {
$$typeof: Symbol.for("react.provider"),
_context: context
};
context.Consumer = {
$$typeof: Symbol.for("react.context"),
_context: context
};
return context;
}
Hooks
So, React provides the Component
class (replaced by plain old javascript functions), it provides types (not required to make the app run), it enables JSX which is syntactic sugar for React.createElement
which, along with React.createContext
, is a helper function to create properly shaped objects.
But it also has that state persistence thing and side effects thing with hooks and all. So for sure it looks like it's creeping into framework territory, right?
const [display, setDisplay] = React.useState(true);
Yeah, about that. React doesn't really do that.
According to Dan Abramov, it's the renderers (react-dom, react-native, and others) that do this, and all of the interesting stuff. Here are a few snippets from his blog post How Does setState Know What to Do?
There is a common misconception that the React “engine” lives inside the react package. This is not true.
In fact, ever since the package split in React 0.14, the react package intentionally only exposes APIs for defining components. Most of the implementation of React lives in the “renderers”.
the base class setState() implementation has been an illusion all along. It doesn’t do anything except forwarding the call to the current renderer. And useState Hook does exactly the same thing.
Okay, so now we know that the react package doesn’t contain anything interesting, and the implementation lives in renderers like react-dom, react-native, and so on.
Case Closed
So React helps developers by providing some niceties, and all the interesting bits are contained in the renderer. So, that seems like case-closed for the library / framework question. But why was this a question to begin with?
I believe the confusion stems from 3 places.
I see value in distinguishing between ReactJS
/ React
and react
. I consider react
to mean the package, and ReactJS
/ React
to mean the ecosystem. The ecosystem is full of mix-n-match plugins, utilities, helpers, systems, patterns, techniques, and whatever's. With enough of these, you could surely build something that resembles a framework.
Until version 0.14, the react
package was all inclusive. It contained all the interesting bits, like state management, context, and the renderer.
And my favorite, calling react a "UI Library". "UI Library" sounds so final to me. Like, "This is the library I use to make UI's". But I've used plenty of libraries to make UI's. Libraries like momentjs. But I would never say I was building a momentjs app. Would you?
Conclusion
In the end, what we call things is a matter of preference, tradition, and expediency. I try to avoid ambiguous terms that have caused confusion, but I'm not dogmatic about it. I won't chew your head off for calling React a framework. Then what's my preference? What do I call it. I think the official website has my favorite description.
React
A JavaScript library for building user interfaces
Posted on December 14, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
March 15, 2022