React is overrated

Video Summary

Video summary of the article in ~6 minutes

Is React Overrated? Yes.

Let me explain why.

So where am I coming from? If you wanna know about me or why my opinion may have some merits, head on over to this page.

I also have to say that this article may appear as offensive to many people but that’s not my intention. I think many web dev content creators are straight-up not honest in their opinions when it comes to react. Which is probably because react is the most popular framework and there are a lot of people interested in knowing more about it and learning it. Telling people that react is not the best choice for building modern UIs may drive these people away. This is the reason why I think we need more honest opinions.

I think react was great when it was released (just like jQuery was before react, vue and angular). But right now, react is just over-hyped, over-rated, bloated and no-fun to work with and should be abandoned in favour of better alternatives.

I will be using vue to compare code just because I have to choose one and vue is the second most popular framework out there. But you could also use svelte code snippets and it would not have changed a thing.

Good things about React

I am not a react hater. I would like to appreciate react first for a few things. (If you are not interested, move on to the next section. This section is not the point of this article.)

React changed the web when it came out. It was a much better choice to build UIs at that time. This is what I am grateful to react for:

  • React popularised the concept of components.
  • React introduced composition, with hooks

Choosing the tech stack for a project

So why do you need React in the first place? You are building a frontend application and you have a plenty of tools available, just for that. But how do you know which one’s better?

Well, there are two parties involved:

  • the product owner
  • the developer(s)
  1. The product owner just wants the thing that they can sell as soon as possible. so the ideal framework for this would be the one that makes the developer more productive.

2. The developers just want their life to not suck in the process. They want a good developer experience and they don’t want to do a lot of work for simple things.

3. There are other important factors too. Like what if some of the developers leave mid-project? You want a well known framework so there are always developers available to pick up where they left.

4. And last but not least you want the project to be scalable so it does not become a pain to maintain it or add new features to it when it grows. And believe me when I tell you, the product in the planning phase and the product that actually sells later on are usually very very different. So you have to rewrite and / or rethink most of the implementation.

5. Performance??? REALLY??

Okay, some of you might be thinking, you didn’t include performance as a deciding factor? Are you crazy?

Well my response to that will be:

Really? you think react is the most performant framework library out there?

Raise your hand if you want me talk about react’s performance.

Yeah, that’s what I thought.

But jokes aside, it may come as a surprise to you, but the performance of these js frameworks rarely matters when building a web application. All of them are fairly performant.

So lets break it all down:

Productivity

Ok, Productivity… Does react make you do things faster than ANY other framework out there?

Or do you always have to fight the framework to do everyday things?

There are a number of reasons why react is not as productive as other frameworks. I will use vue as an example but others like svelte can also be compared.

Footguns, the framework

There are a lot of ways in react to shoot yourself in the foot. The dependency arrays in useEffect and useMemo are one example.

// React:
const cost = useMemo(() => {
    let selected = testTypes.find(t => t.name === testType)
    let price = selected?.price || 100
    if (age > 50) price *= 0.8
    return price
}, [testType, age])
// vue:
const cost = computed(() => {
    let price = testType.value?.price || 100
    if (age.value > 50) price *= 0.8
    return price
})

You are required to define what values should react watch to perform an effect or calculate a computed value. Why does it not do it automatically??

You have to write code, explicitly, to tell react not to eat your RAM alive.

Also, did you know that any time the state or props of a component change, react re-runs this ENTIRE component function? So be mindful not to trigger unnecessary render cycles. Again, it should only have updated the parts of the component that needed changes but I guess react is not as intelligent as a spreadsheet that was created like 50 years ago.

It’s like react was designed to to trick you into writing buggy code unless you do the donkey work.

Its just Javascript dude!

Another example is using plain javascript in react. I laugh so hard when people say, hey react is simple, its not a framework, its just javascript. I haven’t seen an argument so wrong, yet so popular, in my entire lifetime. When I see developers make this argument, the very developers who are supposed to be logical and reasonable, I kinda believe that developers are doomed and may be ChatGPT will (and should) take over their jobs.

If react was just javascript, everyday stuff like setInterval should work as expected and Dan Abramov should not have to write an article to explain and fix setInterval in react.

If react was just javascript, you should not need a wrapper around every frickin js library to make it work with react.

Basically, around half of the code in react is to do the stuff that you want to do and half of it is just to make sure react doesn’t misbehave.

But (vue / svelete) is magic!!?

I have heard many YouTubers / tech-gurus / tech influencers say something like:

Well, X framework is good but it uses a lot of magic and magic is bad! React is king because it is just javascript and what you write is exactly what happens when you run it.

GigaChad, the YouTuber

Well, I beg to differ.

What do you think the following component will render when clicked?

// vue component

<script setup lang="ts">
const number = ref(0)
const number2 = ref(0)
const number3 = ref(0)

const addToNumbers = () => {
    number.value = 1
    if (number.value === 1) number2.value = 2
    if (number2.value === 2) number3.value = 3
}
</script>

<template>
    <div>
        <button @click="addToNumbers">Click</button>
        <p>{{ number }} {{ number2 }} {{ number3 }}</p>
    </div>
</template>

// yep, it renders 1 2 3 when the button is clicked, simple!
// react component:
export default function ConditionalState() {
  const [number, setNumber] = useState(0)
  const [number2, setNumber2] = useState(0)
  const [number3, setNumber3] = useState(0)

  const addToNumbers = () => {
    setNumber(1)
    if (number === 1) setNumber2(2)
    if (number2 === 2) setNumber3(3)
  }

  return (
    <div>
      <button onClick={addToNumbers}>Click</button>
      <p>{number} {number2} {number3}</p>
    </div>
  )
}

// it renders:
// 1 0 0 on first click
// 1 2 0 on second click
// 1 2 3 on third click

Another example, what do you think will this component render on the screen and what will it print in the console?

import { useEffect, useRef, useState } from 'react'

export default function Refs() {
  const ref = useRef(0)
  const [a, setA] = useState(0)

  useEffect(() => {
    let i = setInterval(() => {
      console.log('inside setInterval', a, ref)
      setA(a => a + 1)
      ref.current = ref.current + 1
    }, 1000)

    return () => {
      clearInterval(i)
    }
  }, [])

  return (
    <div>
      <div>a: {a}</div>
      <div>ref.current: {ref.current}</div>
    </div>
  )
}

// tested on react 16.2 and react-dom 16.2
// I hear the screen render is fixed in later versions 
// but the console part is still the same

If react is not magic and does exactly what you write, both the screen and the console should print 0 0, 1 1, 2 2 and so on. After all, react is just javascript, right?

Nope!

Unnecessary code

Another factor that kills productivity is unnecessary code. React makes you write unnecessary code. A lot!

Lets take a look at a simple example. Every app has some kind of state. Lets say we want to have a theme toggle switch in our app. So we need three things:

  1. A store for current theme
  2. A toggle component
  3. Use the toggle component in our main container

Here’s how we define a store in vue:

import { defineStore } from 'pinia'

export const useThemeStore = defineStore('theme', () => {
  const theme = ref('light')
  
  function toggle() {
    theme.value = theme.value === 'light' ? 'dark' : 'light'
  }
  
  return { theme, toggle }
})

This is how it looks in react:

import React, { createContext, useState } from "react"

const ThemeContext = createContext()
const ThemeProvider = function (props) {
    let [theme, setTheme] = useState('light')

    let context = {
        theme,
        toggle() {
            setTheme(theme => theme === 'light' ? 'dark' : 'light')
        }
    }

    return (
        <ThemeContext.Provider value={context}>
            {props.children}
        </ThemeContext.Provider>
    )
}

You could also use a newer react feature called useReducer. I haven’t used it, but it just looks worse.

Next, lets create a component that uses this state. Here’s how you would do it in vue:

<script setup lang="ts">
import { useThemeStore } from '~/pages/store/theme'

const theme = useThemeStore()
</script>

<template>
    <button @click="theme.toggle">{{ theme.theme }}</button>
</template>

And here’s the same in React:

import React, { useContext } from "react"
import ThemeContext from 'contexts'

function Toggler() {
    let theme = useContext(ThemeContext)
    return (
        <button onClick={theme.toggle}>{ theme.theme }</button>
    )
}

Finally, lets use this component in our main container. Here’s vue:

<main :class="theme">
    <h1>Store Example</h1>
    <ThemeToggle/>
</main>

And here’s react:

<ThemeProvider>
    <main className={theme.theme}>
        <h1>Context Example</h1>
        <Toggler/>
    </main>
</ThemeProvider>

Now, you might say, well who uses context? context sucks. Use redux. To that I say, one, what the heck is context doing on react’s documentation site then? I see context there, not redux. And 2nd, redux sucks even more. In a practical redux app, this is what it looks like:

import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { withRouter } from 'react-router-dom'
import Navbar from '../components/navbar/Navbar'
import * as appActions from '../actions/app'
import * as sitemapActions from '../actions/sitemaps'
import { hasFreeTrial } from '../selectors/profile'

function mapStateToProps(state) {
    const instances = Object.values(state.sitemapInstances)
    return {
        profile: state.profile,
        hasFreeTrial: hasFreeTrial(state),
        isLoggedIn: !!state.profile.data,
        sitemaps: Object.values(state.sitemaps),
        plan: state.account.current.plan,
        instances
    }
}

function mapDispatchToProps(dispatch) {
    return {
        actions: bindActionCreators({
            ...appActions,
            ...sitemapActions
        }, dispatch)
    }
}

export default withRouter(connect(
    mapStateToProps,
    mapDispatchToProps
)(Navbar))

This code is doing absolutely nothing of value. This scary looking code is just here to connect the store to the UI. Why is it more than a single line of code? Why cant we just import the store and use it? (Btw, I’ve also used redux toolkit. And its just sad to see that they tried to fix redux and this is what they came up with.)

It is not just with this particular use case.

Want to bind an input to the state?

// react:
value={age} onChange={e => setAge(e.target.value)} 
// vue 
v-model="age"

Want to define state?

// React: 
const [name, setName] = useState('Naveed')
// Vue: 
const name = ref('Naveed')

Want to declare a computed state that depends on some other state?

// react
const cost = useMemo(() => {
    let selected = testTypes.find(t => t.name === testType)
    let price = selected?.price || 100
    if (age > 50) price *= 0.8
    return price
}, [testType, age])

// vue
const cost = computed(() => {
    let price = testType.value?.price || 100
    if (age.value > 50) price *= 0.8
    return price
})

I could go on and on but you see the pattern. React makes you write a lot of code that doesn’t do anything. Instead of focusing on what needs to be done, react forces you to write a lot of boilerplate which is just a waste of time and energy.

Developer Experience

Being non productive doesn’t really give a great developer experience. And the reasons I talked about above make you frustrated with React. You have to write a lot to do very little.

You write so much yet you do very little!

Also the things you have to do to just make react not go off the rails is just silly.

Now, experienced react developers are gonna jump in and say:

You can write good code with react if you know react well. If you write bad react code, it is a SKILL ISSUE. React improves your javascript skills, you see. It forces you to consider best practices when it comes to performance.

GigaChad, The Senior React Developer

To that I am gonna say, first, if you get used to the suffering, it doesn’t make the suffering good. For a long time, we’ve been doing this. We glorify unnecessary over-engineering and over-complication. It needs to stop.

And just because you can, doesn’t mean you should. You want a tool that you can reliably use. I don’t want this tool become my mom and punish me for forgetting something that this very tool was supposed to take care of. If I wanted to improve my javascript skills, I would go learn javascript before taking someone’s money to build their project.

Maintainability

It is much easier to maintain a vue project or a svelte project than a react project. With react it always feels like you are fighting the framework on efficiency and performance. I will not post any examples here because I gave plenty in the previous sections.

Developer Availability

There are a lot of react jobs out there and a lot of react developers because of that. There is no denying that. But developer availability alone should not be the deciding factor when choosing a framework.

React was created before vue or svelte and it has a huge marketing and hype behind it. It does not mean it’s better. It just means that Facebook / Meta has more developers in the world to choose from. Just because Coke is everywhere, doesn’t mean it’s the best drink in the world.

Conclusion

At the end, if I offended anyone in anyway, I am sorry. The purpose of this article is to educate people and to get educated by the comments on this article in case I missed something. We, as software engineers, should be logical and reasonable. But sometimes, we just fall victim to the hype and marketing of a tool and this leads to bad things for not just us, but the future developers as well. Look at where we are now in web development. It took us around 10 years to get back to where we were at the beginning. From SPA to SSG to SSR and Server components. How many man hours we waste globally to learn stuff that we should not have to learn in the first place.

  • React is not productive when compared to the alternatives
  • React does not provide a good developer experience when compared to the alternatives
  • React application is a pain to maintain when compared to the alternatives
  • React has the worst performance than the alternatives
  • React has more jobs in the market but that is purely based on hype and we as decision makers should consider other frameworks to make web development overall better for everyone

React came a long time ago and was great at the time. With time, better frameworks emerged. I personally have used React, Angular, Vue and Svelte. And I think that Vue and Svelte are objectively better alternatives to React. Anything that react can do can be done more efficiently and elegantly with other frameworks.

P.S: I see some changes in React 19 that are the steps in the right direction. But react still has a lot of catching up to do. May be some day, it will fix these issues and redeem itself like PHP did. I am hopeful, but wouldn’t bet on it.


Comments

2 responses to “React is overrated”

  1. Muhammad Ali Avatar
    Muhammad Ali

    Couldn’t have said it any better. It almost feels like most of the youtubers are being paid to talk about react (either sponsored or react fan-base= large audience = more views = more money).
    In my opinion, the react team got it all wrong, i.e., instead of reducing the complexity and thus reducing number of lines as a byproduct, they implement something and then make something else to make the first thing work (take example of context providers for example, creating a context is not enough, you have to wrap it in a provider and then also wrap the App component in a provider to be able to use this context. Now imagine the kind of pyramid you will end up with in your app level component incase you got multiple contexts)
    I am not saying Vue didn’t make mistakes like this along the way (remember the boilerplate in Vue2 and VueX), but they were smart enough to realize they could clean and simplify it in the next releases which they did (Vue3 and Pinia). That’s what’s all this is about, simplifying the experience for the developer. Maybe either React team doesn’t care about simplification, or maybe they are trying so hard to come off as a “standardized” frontend framework where things are strict and you gotta keep in a certain line for it to work.
    I worked with React Native with for some time and had to use Redux for state management. It was okay-ish in the beginning when there were very few features but as the app started to grow, so did the nightmare. Since the react functional component reruns for every component update (either state or prop), it started dropping performance. One solution was to make every little thing a separate component, but there’s a limit to where you can keep isolating everything into its own separate component, otherwise, it gets too time consuming and non-productive. On the other hand, as the app started to grow in terms of stores, the immutability of Redux state started to deplete performance even more. Consider this, you have to update a single value in a big ass store, but it is immutable so you have to create a new copy of it and apply the change, then the change causes whatever relevant functional components to re-render again. Does it get the job done? Yes it does. Is it the optimal experience? No it is not. Could it have been done better? Of course!
    Anyways, if it makes react developers feel they achieved a lot by typing a lot of unnecessary stuff that should have been take care of by the framework itself, good for them. I am not stopping anyone from going that way or judging their choice of framework, its not even a war of X framework vs Y framework, its a matter of personal preference in terms of developer experience + simplicity of implementation + easiness in maintainability. If React fulfills these aspects someday, I might not even think twice before switching to it.

  2. I have extensive experience in both React and Vue.js, with over a decade of development experience. In my opinion, Vue.js is an excellent framework, and those who prefer React simply have not had the opportunity to work with Vue.js. They may mistakenly believe that the React way of doing things is the industry standard.

    Thank you for the informative article.

Leave a Reply

Your email address will not be published. Required fields are marked *