DEV Community

andrescasa-dev
andrescasa-dev

Posted on

Excel in React by understanding JSX under the hood

Sometimes working with JSX is weird, because we are thinking the component like a direct representation of HTML, but as all we know JS doesn't support HTML, don't we? And that misconception is a big slowdown in the process of mastering React or in the process to start learning it.

To overcome this misconception is important to know what is actually JSX, because when we write a React component we aren't writing a function that produce HTML murk up, but instead a function that produce a JS literal Obj.

Lets consider the following small component:

import { AlertOctagon, Info } from "react-feather"

export default function Notification({ msg, type}) {
  const iconDictionary = {
    'informative': Info,
    'error': AlertOctagon
  }

  const Icon = iconDictionary[type]

  return (
    <div>
      <span>
         <Icon />
       </span>
      <p>{msg}</p>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

The Notification Component receive two arguments msg and type, also depending of the type it will render a certain Icon.

It could be a little strange to a newbie of React storing a Component inside of a object ¿How is it possible? JS doesn't support HTML, all we know that. But this code doesn't do it, in a deep level it is storing a React Element (it some cases a function that return a React element but this is not the case). And a React Element is a Obj with certain properties provided by React library. And all we know that storing objects is totally normal in JS.

There is not magic, JSX is not a black hole, they are just functions. But how it works? why we can easily "write html" and use JS functionality. That's the real magic and i'm going to unfold it right know.

There are 3 important steps to consider.

1. Developer writes JSX

In this step the React team apply syntactic sugar called JSX in order to create faster the HTML elements, ending up in experience like working with HTML but with the power of JS. However, it isn't valid JS it is just a bunch of conventions, imaginary rules that the machine doesn't understand but help us to be quickly.

import { AlertOctagon, Info } from "react-feather"

export default function Notification({ msg, type}) {
  const iconDictionary = {
    'informative': Info,
    'error': AlertOctagon
  }

  const Icon = iconDictionary[type]

  return (
    <div>
      <span>
         <Icon />
       </span>
      <p>{msg}</p>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

2. A transpile tool converts the JSX into JS

a tool like babel enter to our scene, its work is to produce real executable JS from the JSX . This process is trigger in building time. and it produce something like this:

import { AlertOctagon, Info } from "react-feather";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
export default function Notification({ msg, type }) {
  const iconDictionary = {
    informative: Info,
    error: AlertOctagon
  };
  const Icon = iconDictionary[type];
  return _jsxs("div", {
    children: [
       _jsx("span", {
        children:
           _jsx(Icon, {})
      }),
       _jsx("p", {
        children: msg
      })
    ]
  });
}

Enter fullscreen mode Exit fullscreen mode

Babel (in this case) adds a new import "react/jsx-runtime" and As you can see, now the "html tag" are written as calls of the _jsxs utility funciton, This one produce React elements and is very similar to createReactElement ¿What are React elements? and ¿why they are not HTML? lets see.

3. The JS code runs and it produce a Virtual DOM

At this point we built our app and the server is ready to send a copy of the JS. So when a user make a request and its browser loads the code (using SSR of course) the _jsxs funciton will run and they produce something like this:

{
  "$$typeof": Symbol.for("react.element"), // Type of the element (React Element)
  "type": "div", // Type of the HTML element
  "key": null, // Key for the element (null in this case)
  "ref": null, // Ref for the element (null in this case)
  // here would go more stuff of react
  "props": { // Properties of the element
    "children": [
      {
        "$$typeof": Symbol.for("react.element"),
        "type": "span",
        "key": null,
        "ref": null,
        // here would go more stuff of react
        "props": {
          "children": [
            {
              "$$typeof": Symbol.for("react.element"),
              "type": Info, // React component used as the icon
              "key": null,
              "ref": null,
              "props": {} // Props for the icon component (empty in this case)
            }
          ]
        }
      },
      {
        "$$typeof": Symbol.for("react.element"),
        "type": "p",
        "key": null,
        "ref": null,
        // here would go more stuff of react
        "props": {
          "children": "This is an informative message." // The message prop
        }
      }
    ]
  }
}
****
Enter fullscreen mode Exit fullscreen mode

This is the Virtual DOM, a tree structure that React use to optimize the render process and create the Native DOM elements (the HTML in roughly) and all this structure lives in the memory of the user. Each node of this Tree is a React element. And React has a whole process to transform this Elements in a Real HTML that the Browser can show to the user. But we tackle that monster in another battle. For now, keep in mind that ReactElements are blueprints (JS literal objs) that React use in another process to produce HTML. They are not directly HTML.

So that's it. JSX is just way to write a function that produce a JS object with a fancy name. And this mindset will help you to quickly familiarize with common React Patterns, as so as the one that we previously overcome, but also the slot pattern, polymorphism, prop delegation and other patterns that will help you to write reusable and easy to use components.

Top comments (0)