React single file components

— 4 minute read

The idea of having all component code in one file is not new. Vue.js and its Single File Components populated it. In the React ecosystem, this idea is not very popular. Probably, because there is no official way to do it.

In the React ecosystem usually component consists of two files: logic/markup and styles. Logic and markup are JS and JSX, while styles could be anything: regular CSS, CSS modules, PostCSS, Sass, CSS-in-JS solutions.

I'll be looking at the CSS-in-JS variant because this is what my teams are using. And specifically styled-components (and similar solutions).

One of the most annoying things when working with styled components for me is having to change many places, when I add, remove or rename a styled component. It's not a styled-components library annoyance, it's how developers decided to use it in their projects.

To add a new styled component we need to add it in style file. Then import it, and only then we can use it. To delete a component, we need to remove code that is using it, then remove import, and only then remove the styled component itself. Renaming a component is the same annoyance. Too much changing between files and jumping around, while we still working on the same entity.

Having component code (markup, logic, styles) in a single file simplifies the development flow. Everything happens in one file and eliminates the import/export juggle.

I suggest putting styled components at the end of a React component file because we work with logic and markup much more than with styles.

import React from 'react';
import styled from 'styled-components';

export default function Post(props) {
return (
<article>
<Title>{props.title}</Title>

<Content>{props.children}</Content>

<Footer>Published on {props.date}</Footer>
</article>
);
}

let Title = styled.h1`
margin-bottom: 24px;
`
;

let Content = styled.div`
margin-bottom: 24px;

p:not(:last-child) {
margin-bottom: 8px;
}
`
;

let Footer = styled.footer`
border-top: 1px solid #000;
padding-top: 24px;
`
;

What if I want to see markup and styles side-by-side in my editor? How would I do it with a single file?

Two editors, I've been using the most, support having one file open in two or more panels. For Sublime Text, it's File → New View into File menu item. For VS Code, it's any of Split commands in View → Editor Layout menu (or a button at the end of a tab bar with a square divided in the middle icon). Most likely other editors have the same functionality.