Lessons learned from rewriting React in Javascript

Posted on 2024-10-04

In an effort to reduce the complexity of our developer documentation hub at work, I've been diligently working to remove all React components/interfaces that we use and replace them with pure HTML/CSS/JS components as God intended. We use React simply because we interface with the company's design library, which is written in React. We did this because we thought it would reduce the workload on us, allowing us to simply inherit changes from the UI/UX teams in our project. In reality, it turns out that updating CSS is far simpler than trying to implement complicated APIs that were never supposed to work with markup languages like Markdown.

So, I've been ripping all of that stuff out as a way of making the site lighter and improving my own understanding of Javascript. In the new approach, we use semantic HTML to choose the correct tag type (rather than just a HUGE nested list of divs, as many people are wont to make these days) then style them with CSS. In most cases, this is sufficient. There are a few places where Javascript is necessary, however, and it's here that I've really learned to dislike React.

There are two things that bother me about React in this scenario:

1. It's usually unnecessary and adds a lot of complexity

2. Or it hides the complexity and causes you to write badly

To explain, let me give you the example of tags. We wanted synchronized tags in our writing, so I asked my senior developer to write some logic that would allow us to write something like the following:

<Tabs>
<Tab title="Kotlin" sync="kotlin">
...content
</Tab>
<Tab title="Java" sync="java">
...content
</Tab>
</Tabs>

This allowed us to do really cool stuff like having non-matching titles on syncing tabs and complex nested tag structures. In React, this is quite easily achieved. In vanilla JS, however, it's much more complex.

Is this a problem with Javascript? Not really. It's just a bad way of authoring things. Instead, you should really be grouping tabs by sync ID and then selecting them using titles like:

{% tabs sync="android" %}
{% tab title="Kotlin" %}
...content
{% /tab %}
{% tab title="Java" %}
...content
{% /tab %}
{% /tabs %}

This is far easier to work out in vanilla JS and ultimately maeks for more concise writing. Had we used vanilla JS from the start, we may have just decided to change the authoring style to make it easier to implement. But React was too effective a crutch, so we stuck with it.

Is the original logic impossible to implement with inline JS? Of course not. It's just annoying. You have to check siblings and a whole bunch of other nonsense. That kind of thing leads to applying limits to writing, which is ultimately a positive.

✉️ Tell me what you think