preface

When writing components, I was most puzzled by why I needed to import React when I was writing purely functional components without calling React in the code. After some research, I found it was because of JSX translation Settings. Install the babel-plugin-react-require plugin to automatically import react. This article will describe my research experience and some reflections.

Let’s say we have an app.js file, which is equivalent to Hello World.

import React from "react"; const App = () => ( <div>Hello World!!! </div> ); export default App;Copy the code

why

When Babel translates our app.js, it converts the JSX syntax sugar to the react. createElement method.

var App = function App() {
  return React.createElement(
    "div",
    null,
    "Hello World!!!"
  );
};Copy the code

You can see how Babel is translated at Babel REPL.

Automatic introduction of React

For React front-end projects, we can write pure function components directly without introducing React statements at the top: import React from ‘React ‘; ?

The answer is yes, we can use babel-plugin-react-require to automatically identify stateless components and then, if so, automatically introduce react.

Installation method

We can install directly through NPM

npm install babel-plugin-react-require --save-devCopy the code

Then add react-require at.babelrc

{
  "plugins": [
    "react-require"
  ]
}Copy the code

Note that react-require needs to be introduced before transform-es2015-modules-commonjs, because the plugin requires es2015 modularity statements to import react into the domain.

example

If we wrote a purely functional component, the code would look like this:

export default function Component() {
  return (
    <div />
  );
}Copy the code

The babel-plugin-react-require plugin will automatically translate the above code into the following code:

import React from 'react'; Export default function Component() {/* Return (react.createElement ('div')); }Copy the code

Custom translation methods

So we can think about it a little bit more if instead of using React, we use some other method in the React ecosystem. Deku, for example, is a library for using pure functions and virtual DOM rendering interfaces. It’s part of the React ecosystem.

Can we rewrite the translated method and not use the React. CreateElement method?

The answer is yes.

@babel/plugin-transform-react-jsx allows us to add /** @jsx method names */ at the top of the file, or globally modify.babelrc.

For example, code like this:

/** @jsx dom */

var { dom } = require("deku");

var profile = <div>
  <img src="avatar.png" className="profile" />
  <h3>{[user.firstName, user.lastName].join(' ')}</h3>
</div>;Copy the code

This translates to the following code:

/** @jsx dom */

var dom = require("deku").dom;

var profile = dom("div", null,
  dom("img", { src: "avatar.png", className: "profile" }),
  dom("h3", null, [user.firstName, user.lastName].join(" "))
);Copy the code

Pieces of the React

What about the new Fragments added to React 16.2.0? /** @jsxfrag function name */

Input:

/** @jsx dom */
/** @jsxFrag DomFrag */

var { dom, DomFrag } = require("deku");

var descriptions = items.map(item => (
  <>
    <dt>{item.name}</dt>
    <dd>{item.value}</dd>
  </>
));Copy the code

Output:

/** @jsx dom */
/** @jsxFrag DomFrag */

var { dom, DomFrag } = require("deku");

var descriptions = items.map(item => dom(
  DomFrag,
  null,
  dom("dt", null, item.name),
  dom("dd", null, item.value)
));Copy the code

You can open the Babel Rep-React Fragment to debug code in real time.

Installation method

You need to install @babel/plugin-transform-react-jsx to convert JSX syntax. If not, you can install it via NPM.

npm install --save-dev @babel/plugin-transform-react-jsxCopy the code

Global changes

Write the following snippet in.babelrc:

{
  "plugins": ["@babel/plugin-transform-react-jsx"]
}Copy the code

We can modify the react. createElement by modifying pragma globally.

{ "plugins": [ ["@babel/plugin-transform-react-jsx", { "pragma": "dom", // React.createElement "pragmaFrag": "DomFrag", // react. Fragment "throwIfNamespace": false, // Throw exception "useBuiltIns" if the tag name of the XML namespace is used: False // Use object. assign instead of Babel's built-in extension (extend)}]]}Copy the code

The resources

  1. Why import React from “react” in a functional component?
  2. @babel/plugin-transform-react-jsx
  3. anthonyshort/deku – Github
  4. vslinko/babel-plugin-react-require – Github