Reverse Engineering Styled Components

Shreyans Jain
March 01, 2020

The idea

I recently attended a ReactDay Meetup in Berlin and was astounded by an awesome talk by an amazing speaker & a mentor, Tejas Kumar. His talk was called "Destructuring React" and instead of a bunch of slides, he amazed everybody by live-coding "Poor Man's React" (his words).

Starting from scratch, he reverse-engineered some React functions like createElement & useState building them in vanilla JS. This idea struck me making me believe that it is possible to do the same for many other libraries.

Here's how it goes:

  • Create empty directory with entry files - index.html & index.tsx
  • Use parcel to serve index.html
  • yarn add react react-dom

index.html

<div id="app"></div>
<script src="index.tsx"></script>

To begin with, I am going to create a bunch of "styled" components and render them using React. Remember, I did not install the styled-components library, because I am going to create it!

index.tsx

import React from 'react'
import ReactDOM from 'react-dom'

const RedH1 = styled.h1`
  color: red;
`

const RedH2 = styled.h2`
  color: red;
`

const RedH1WithYellowBg = styled(RedH1)`
  background: yellow;
`

const App = () => {
  return (
    <>
      <RedH1>I am red</RedH1>
      <RedH2>I am blue</RedH2>
      <RedH1WithYellowBg>I am red &amp; yellow</RedH1WithYellowBg>
    </>
  )
}

ReactDOM.render(<App />, document.getElementById('app'))

Guess what happens when I serve this? I get an ERROR!

Uncaught ReferenceError: styled is not defined

To create my own styled-components library, I will create a file styled.ts, but to even start writing code there, we need to understand the styled-components API (how it works). According to their official documentation, a styled component can be defined in the following way

const StyledH1 = styled('h1')`
  /* css goes here */
`

This means that styled is a function which accepts "tag" as an argument returns another function that is a "Tagged template". According to MDN: "Tags allow you to parse template literals with a function. The first argument of a tag function contains an array of string values. The remaining arguments are related to the expressions."

To test this logic, I am going to create a function called styled that just logs all the arguments that are passed to it.

styled.ts

const styled = (...args1) => (...args2) => {
  console.log({ args1, args2 })
}

Testing this with a few different examples of typical styled components, we get the following results

const StyledH1 = styled('h1')`
  color: red;
`

We get

{
  args1: ["h1"],
  args2: [["\n  color: red;\n"]]
}

When I try to render that component like

<StyledH1>Red Heading</StyledH1>

we get an error

Tech & Product Design Consultancy