Why Did And Don’t You Need To Import React
March 13, 2022 - 3 minutes
For a very long time in React development, it was necessary to import React
in your JavaScript or TypeScript files that used React components. It wasn’t until React v17.0, which was released in August of 2020, that React introduced a new transform feature that allowed its developers to not have to do this anymore.
But why did we have to import it in the first place? What was the reason that we had to add this seemingly unused import every time we created React components? And why do we ‘suddenly’ not need it anymore?
The Reason We Needed It
If you’re unfamiliar with React development, it’s composed of a ton of so-called React components. The main philosophy behind React development is creating small components that can be reused and composable in different scenarios. To create React components, the standard is to use JSX which is a syntax extension to JavaScript.
An example of how such a component and JSX look is as follows:
import React from "react";
function Card({ content }) {
return (
<div>
<CardBody size="medium">{content}</CardBody>
</div>
);
}
For most React developers, this will feel very familiar. It’s a straightforward Card
component that accepts one prop. The component itself renders some HTML, a singular div
, and another random React component called CardBody
. To that latter component, we pass 2 props: the content
prop that Card
received as its children
and a static value for its size
prop.
Nothing fancy going on here. But in its current form, the browsers can’t do anything with it. As mentioned, JSX is a syntax extension created on top of JavaScript. The browser doesn’t understand JSX so when it tries to evaluate this code, it will just throw an error.
What does this have to do with having to import React
? Well, ultimately your React code still has to be received and rendered by a browser. But rather than its current form, it will first be transformed into a form that the browser can understand: regular JavaScript. That would look as follows:
import React from "react";
function Card({ content }) {
return React.createElement('div', null, React.createElement(CardBody, { size: 'medium' }, content));
}
All the syntactic sugar was removed and transformed to their respective JavaScript equivalents. Based on this, we can see that creating a React component using JSX is nothing more than a function call using 3 function arguments: the type of the component, its props in an object form, and its children.
But the most important thing to note is the function itself. Under the hood, React components are createElement
calls and that function comes from React
. Based on that, we can go back to the original question of this article and understand the necessity to import React
whenever we created a React component. Without it, the transformed JSX code would fail in the browser as React needs to be in scope to create components through its createElement
function.
The Reason We Don’t Need It Anymore
So now that we know why we needed it before, the next interesting question becomes why we suddenly don’t need it anymore. What changed in React v17.0 that set us free from having to perform this annoying and seemingly unused import of React
in every file that uses JSX?
In short, React moved the functions for creating elements towards new entry points. Instead of relying on the createElement
function that is exposed in the main entry point of the package, it was split off into entry points that are intended to be only used by compilers, like Babel and TypeScript.
So now while transforming JSX, compilers can, and will, automatically import the appropriate functions from those new entry points. This means that developers don’t have to manually add the React
import as compilers don’t have to rely on the main entry point anymore. The example code, before and after transformation, will now look as follows:
function Card({ content }) {
return (
<div>
<CardBody size="medium">{content}</CardBody>
</div>
);
}
// Inserted by a compiler
import { jsx as _jsx } from 'react/jsx-runtime';
function Card({ content }) {
return _jsx("div", {
children: _jsx(CardBody, { size: "medium", children: content })
});
}
This feature was also backported to most of the older React versions for backwards compatibility. If you want to learn more about how you can also upgrade to this new JSX transform, it’s recommended to take a look at the upgrade guide.