DEV Community

Cover image for Single-File Components in React: Genius or Garbage?
Samir Tahiri
Samir Tahiri

Posted on

Single-File Components in React: Genius or Garbage?

Let’s start a fight (respectfully) 🥊

Recently, I came across a few React projects where the entire component was written in one file — logic, styles, markup, all jammed together.

Example:

// Button.jsx
import './Button.css';

function Button({ label }) {
  const handleClick = () => {
    alert('Clicked!');
  };

  return <button onClick={handleClick}>{label}</button>;
}

export default Button;
Enter fullscreen mode Exit fullscreen mode

They call this "Single-File Components (SFC)". The idea? Keep everything together: no more .js, .css, .test.js, etc.

But here's where it gets spicy 🔥


🧠 The Argument For SFCs

  • 🪄 Easier to read and understand in one glance
  • 🚀 Less context switching between files
  • 📦 More portable (copy one file, done)
  • 🧼 Cleaner when using CSS-in-JS or Tailwind

😤 The Argument Against SFCs

  • 🤯 Can get bloated fast (200+ lines easy)
  • 🧪 Tests get ignored or written elsewhere
  • 💣 Harder to scale in large teams
  • 📁 Violates Separation of Concerns (SoC)

💬 What Do You Think?

Do you love the simplicity, or do you miss the old-school modularity?

👇 Comment below:

  • Do you use SFCs in React?
  • What are the pros and cons you’ve experienced?
  • Would you recommend it to your team?

Let's debate 👇


🗳️ Bonus: React devs — should we embrace single-file components like Vue? Or stick to separation?

React #WebDev #Frontend #DevOpinion

Top comments (17)

Collapse
 
xwero profile image
david duymelinck

Not a React dev. As I see it, a single file component in Vue or Svelte is closer to a web component.

Vue example

<script setup>
import { ref } from 'vue'

const count = ref(0)
</script>

<template>
  <button @click="count++">You clicked me {{ count }} times.</button>
</template>
Enter fullscreen mode Exit fullscreen mode

Here the separation between markup and logic is more visible.
In React it is a function with logic and markup.

Collapse
 
ivan_jrmc profile image
Ivan Jeremic

That's not how web-component definition looks like. Read on MDN on how to create and define custom elements and you will see.

Collapse
 
xwero profile image
david duymelinck

I mentioned it is closer, not that it is a web-component definition. I added the link to MDN, that would be stupid if i didn't read it first.

Thread Thread
 
ivan_jrmc profile image
Ivan Jeremic

not even closer, makes no sense. A web-component is defined by doing. class MyComp extends HTMLElement

Thread Thread
 
xwero profile image
david duymelinck

From MDM:

<template id="custom-paragraph">
  <style>
    p {
      color: white;
      background-color: #666666;
      padding: 5px;
    }
  </style>
  <p>My paragraph</p>
</template>
Enter fullscreen mode Exit fullscreen mode

Doesn't that look a lot like a Vue or Svelte component?

Thread Thread
 
ivan_jrmc profile image
Ivan Jeremic • Edited

That is not a web-component. Your link just shows an example of how the template tag can be used with web-components but this is not a web-component.

Thread Thread
 
xwero profile image
david duymelinck • Edited

If a template is used by a web component, how is that not web component syntax?

What you think a web component is, class MyComp extends HTMLElement, is a custom element. This also can be created by using <my-comp></my-comp>, .
Web component is not a strict definition. It is a set of features in HTML, CSS and javascript that work together. And HTML is the most import part because it is the base.

This is a declarative web component.

<my-comp>
 <template>
  <style>
    p {
      color: white;
      background-color: #666666;
      padding: 5px;
    }
  </style>
  <p>My paragraph</p>
</template>
</my-comp>
Enter fullscreen mode Exit fullscreen mode

Javascript is not a requirement.

Collapse
 
samirtahiri profile image
Samir Tahiri

Thanks David, great point!
You're right – Vue and Svelte with SFCs definitely highlight that clear separation of markup and logic. In React, the JSX + hooks combo can feel more “blended” since everything lives in one function. That’s exactly what I was touching on in the post – how different frameworks structure and think about components.

Both approaches have pros depending on the mindset and team habits. Appreciate the Vue example!

Collapse
 
dotallio profile image
Dotallio

I've tried SFCs for quick MVPs and they do speed me up, but I always end up splitting things out as the project grows. Have you found a sweet spot where SFCs still work for big apps?

Collapse
 
samirtahiri profile image
Samir Tahiri

Totally relate. SFCs are great for fast iteration and MVPs, but yeah — as the app grows, keeping everything in one file can feel cramped. I’ve found that the sweet spot is using SFCs for atomic components or isolated logic/UI pieces, and gradually splitting concerns (like store, styles, or templates) only when complexity demands it.

So basically: start simple, scale structure as needed. You?

Collapse
 
parag_nandy_roy profile image
Parag Nandy Roy

SFCs feel like React’s version of a one-pot meal ..quick, satisfying, but maybe not for a five-course app 😄 Great convo starter..

Collapse
 
samirtahiri profile image
Samir Tahiri

Yea 100%, thanks tho💪🏼

Collapse
 
9opsec profile image
9opsec

This would be two files with the "Button.css" but I am ok with this for simple web sites.

Collapse
 
johanpiquet profile image
Johan PIQUET

I'm a React dev and I love having one file per component and one CSS per component. It makes it much easier for CSS management.

Collapse
 
samirtahiri profile image
Samir Tahiri

Yea 100%, i am with you here. It makes life easier and more structured fr

Collapse
 
parag_nandy_roy profile image
Parag Nandy Roy

SFCs are like pineapple on pizza ...weirdly good in the right context

Collapse
 
dariomannu profile image
Dario Mannu

If SFCs are like pineapple, custard, or strawberry-banana sandwiches on pizza, then yeah, you said everything about SFCs

Some comments may only be visible to logged-in visitors. Sign in to view all comments.