Low Overhead React

· CSS, JavaScript, Planning, React, Workflow · Patrick Smith

“React. Write reusable components. Make your data flow one way. Never directly use the DOM again.” There’s a lot of benefits that a developer gets by using React.

But React is easy to make complex. It’s so very tempting to optimize early. There are a lot of decisions left to you on how to architect your web app.

The techniques listed here will often make your React app have less work to do, and therefore run faster. Implicit performance is a benefit if it means less time later adding optimizations to claw back to a fast experience.

But the primary aim is to make your app easier to write, easier to change, and easier to debug. Less overhead for the person maintaining the code. Writing low overhead React means you can more easily focus on creating that great experience for your users, while not sacrificing the developer experience.

Low Overhead React Principles

  1. Don’t abandon CSS
  2. Choose packages carefully
  3. Ensure every component does at least one thing well
  4. Don’t let every component talk with the world
  5. Don’t attempt to optimize React rendering too early

Don’t abandon CSS

Look, CSS (or SCSS) has its limitations. JavaScript is obviously more capable as a language. But CSS is proven for its task. It is fast. It can declaratively handle focus and active and hover states, and it can handle a variety of media queries. It just works with server rendering, and is interoperable with technology choices other than React.

Use CSS variables to create reusable styles for typography, spacing, colors, and other things that are consistent across components.

html {
  --link-color: orange;

main a {
  color: var(--link-color);

You override CSS variables when rendering by using the style prop:

<article style={{ "--link-color": "purple" }}>

(You can see an example like the above here: https://codesandbox.io/s/react-css-variables-chbsj)

CSS is still evolving. The standards are adding more capabilities. There are new approaches to organizing and reusability. Not to mention layout.

If you use CSS-in-JS, it doesn’t mean you are banned from using standalone CSS. Base CSS files work great for reusable styles across components.

Choose packages carefully

I’ll be honest: there are a lot of heavy packages out there. Calendars. Themeable kits that come with every UI control you can imagine. State and data structure libraries. Many of these dependencies have a big impact on the bundle size, and therefore the time your users will spend waiting for your application.

This doesn’t mean stay from them. Use some, but don’t just add all your first choices. Don’t say yes unless it really provides key value. A package that makes your experience better as a developer (let the team finish faster!) might make your users’ experience worse (let the user start slower!).

Yes, tree shaking can help improve the initial load time, but if you have large packages that you use as the foundation of your app, most of the tree will remain no matter how hard you shake it. And if the shaken out parts are soon downloaded after anyway, you might be consuming a lot of your users’ limited data. We don’t need to pretend NPM doesn’t exist. But we do need to remember that every npm add is also often adding wait time for every user.

Ensure every component does at least one thing well

Presentation vs Controller. Smart vs Dumb. Connected vs Reusable. Organism vs Molecule. There are many ways of categorizing and splitting-up components into specific roles. I’m not going to offer an opinion here because many ways work well. What I am going to ask is to make sure every component has a role it does particularly well.

You might decide this means the single responsibility principle, so that a component can only be purely HTML focused, or purely subscriber focused, or purely Redux connect focused, or purely analytics focused, etc etc. I leave that up to you, because there often is value in a component doing multiple things. If a component is a function, then it serve to reason that it can be made out of multiple other functions, and these functions can have a single responsibility.

All I request is that you ensure each component does at least one thing particularly well. For example: It’s great at producing markup. It’s great at talking to the rest of the app. It’s great at optimizing render times for this particular case. It may well do more, but at the least it is competent in some particular thing.

If it’s not doing a great job at anything in particular, if it’s trying to speak HTML and API and Redux and URL all at the same time, then it might be time to split it up. A dedicated smaller component can focus on a particular task and communicate its intent better. It’s often fine to keep it in the same file.

Don’t let every component talk with the world

A component is easiest to manage when it follows a simple contract: given some input, I will return what I want presented. Different input, different output. No other factors.

A slightly more complicated component contract is that: in addition, I will produce some side effects. I will POST to a server, I will talk to a local data store, I will add an event listener directly to the DOM.

Another more complicated variation is I will read from outside of my props. I will fetch from a server, I will subscribe to the latest changes to a local data store, I will listen to when the window changes size.

These components can get out hand. Many components start talking to many things. When hundreds of components have a direct connection with the local data store or communicate with the server. Or when the user resizes the window and many dozens of components individually want to update themselves.

I’m not advocating for a particular architecture or a particular number of communication points or set a limit to how many components are allowed to talk to the server. I’m saying be mindful of how many connections there are between components and their outside world. Otherwise a couple of simple changes in the outside world can schedule a huge amount of work.

This may not only lead to performance bottlenecks, but it will also make debugging and future changes harder. Which component made that change? If I rename or restructure this reducer, how many components had this knowledge and so will need to be updated? It’s best to make these questions easier to answer by reducing the surface area of connections.

Make smaller worlds for your components by bundling collaborators together, and then export a simpler component that will be used to hide the details and nuance inside. Add single connection points that bridge between one world and another. Add facades with small surface areas your components see, that then go and talk to the larger world, translating back and forth. Don’t just let any random component talk to whatever it likes. It might feel convenient now, but it’ll likely become inconvenient when changes are needed.

Don’t attempt to optimize React rendering too early

Don’t optimize your components until there’s a clear problem to be solved. React is designed so that straight forwardly written components will lead to great performance!

If do you want to apply optimizations, first read the documentation provided:

If these don’t answer your question, then reach out to people from the React core team like Dan Abramov who happily answers people’s questions on Twitter.

Next, measure using the open source React DevTools which is available for Firefox and Chrome.

Measure the current profile by clicking record, performing the particular flow that you wish to make more performant, then stopping the record. Use the interactive charts to see the bottle necks and which components need attention.

Make changes, and profile again. It may take several iterations because your expected optimization technique might make things slower.

If you have existing optimizations like React.memo in place, it might be worth removing them all, and then using the React DevTools profiler to introduce them where you see a meaningful improvement.

Using React.memo relies on every prop passed to a component staying the same (being referentially equal) across renders to skip its own rendering. This can be infectious, leading to all your components having to follow this extra contract on their props coming in. Trying to make everything referentially equal can be a lot more computational work that can lead to other performance overheads. And it’s very easy to pass just a single prop that does not stay consistent (say an arrow function), leading to the intended optimization being never applied.

React. It’s unique selling point is that it makes writing web apps easier. Yet it’s easy with React to find yourself battling complexity, or for users to be getting penalised performance. Being mindful about the overhead that some techniques and third party packages bring helps keep complexity low, performance easy to find, and future changes maintainable.

Typed Subatomic Styling: Part 1 — Benefits of TypeScript and CSS

· CSS, JavaScript, React · Patrick Smith

The benefits of components have been realized with systems such as React and VueJS. Styling these components has a number of approaches, from CSS classes written in SCSS, inline styles, and dynamically generated stylesheets via something like emotion.

Each styling approach has trade-offs in regards to reusability, performance, and developer experience. Also, special considerations often have to be made when doing server-side rendering.

In this post, we’ll explore TypeScript combined with functional CSS. I believe it offers big benefits over the other choices — it’s extremely reusable, fast, and offers a very pleasant developer experience.

Read more…

The difference between CSS Grid and Flexbox

· CSS · Patrick Smith

The CSS Spectrum from Semantic Components to Pragmatic Utilities

· CSS, React · Patrick Smith

A decade or two ago, we usually wrote HTML by hand, whether in templates or as entire pages. Either way, these templates contained raw HTML that formed a structure. They said what was on the page: the semantic meaning behind what presented to the user.

We used ordered or unordered lists, anchors for links, buttons for actions, headings of various priority, and two types of emphasis instead of the predetermined bold and italic elements.

We did this because it made a better experience for our users. They were more accessible, as these semantics could carry over to an audible presentation of the page, or to search engines, or to RSS or read-it-later readers.

But it also made it easier for authors. We had a common language that we could understand and build with. There were various patterns that could be universally understood. You could look at the source code and gleem the intent.

This extended to the styling layer of CSS. Cascading style sheets were separate documents to the pages themselves. Elements on pages would be classed, and in CSS visual rules would be defined for each class. Use the same class on multiple pages, and bam, they would look the same everywhere after having the same rules applied.

Class names could be anything authors desired. They could be single words. They could be multiple words separated by hyphens-like-a-kebab, or allJoinedTogetherWithCapitals. They could have their own little mini hierarchy and system. But, whatever you chose, it didn’t matter. As long as the class names in the HTML and in the CSS matched, they would be applied.

They mattered to authors though. They had to look at them as they made new pages, and evolved the CSS rules. The semantics mattered, and so names that reflected the meaning of the content more than it’s eventual look were desired. A redesign with a new color scheme or rearranged layout could mean throwing all the CSS away if you had names like ‘button-red’ or ‘left-sidebar’. Far better to call them ‘button-danger’ and ‘main-sidebar’, as between redesigns the meaning would stay much the same.

And so we made a rule that CSS class names should not reflect its appearance but its underlying meaning. We broke this rule when we just had to (clearfix anyone?), but doing so was generally regarded as not planning for the future, and, well, just cheating really.

I think in a time of components, we can make some changes. I think we can get rid of many of these semantic CSS classes. Why? Because our components are our semantic layer now.

Remember the structuring of HTML was important for accessibility, but the naming of CSS was really just to make the authors lives easier. Whether a button that looked red to a user had the word ‘red’ in its name or a more considered, meaningful name made no difference to the user. It looked the same, acted the same, and tasted the same (back when UIs looked so good you could lick them).

Components let us organise the building blocks of our pages and UIs into reusables. We can define a DangerButton component, and encapsulated all the styling knowledge inside (whether CSS partials or CSS-in-JS). We can then use this DangerButton in all its glorious meaning again and again, on page after page. When we decide they should no longer be red but bright purple, we have one place to make changes, just like the semantic CSS days.

Our components names and props can convey the full set of meaning, and even better encapsulate not only the styling choices but the amount of HTML too. We don’t need to know the raw elements needed to make a functional link in a navigation bar, we can just use the NavLink component.

So is reusable CSS like we had before encapsulated components dead? I don’t think so.

Utility classes are ultra reusable thin slices of CSS that we assemble to form a complete picture. A DangerButton might have white text on a dark red background, and so we’d use the text-white and bg-red-dark utility classes. We might also sprinkle in text-lg and padding-4 and rounded.

These class names are decidedly not semantic. And they seem to replicate the granularity of CSS rules themselves. Aren’t they just the same as that other villain, inline styles where our CSS is written inside our HTML?

No, because they provide a system. Dark red is defined to one particular shade of crimson and then shared everywhere. The large font size class, text-lg, also can have the exact unit size changed in one exact spot. They might not be semantic, but they don’t spill all their beans.

Plus, they are just plain handy. CSS is fast, caches well, easily made responsive, and works with React or Vue or Elm or Rails. You don’t have to decide which CSS-in-JS library is most in vogue. You don’t even (dare I say) need JS.

Components to utility classes. A spectrum from semantic meaning through to pragmatic efficacy. While it’s not perfect, I think it’s a nice mix of both worlds.