Video Summary
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)
- 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:
- A store for current theme
- A toggle component
- 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.
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.
Leave a Reply