October 2022 Frontend Updates: Data Fetching in React, CSS Container Queries and The Problems and Benefits of CSS-in-JS

This month’s updates:

Data Fetching in React

Data fetching in React can be confusing. There are endless data management libraries, Suspense is called to be the solution but it’s still experimental and loading data inside useEffect has been recently pointed to have some pitfalls:

  • Network Waterfalls: Instead of loading data in parallel, sometimes you could unintentionally end up waiting for every parent above to finish fetching before the child component starts.
  • No Cache: If you go back to the page you will fetch again, unless you use a library or code some custom caching logic.
  • No Server Side Rendering: Effects don’t run on the server, so you won’t be able to pre-render any useful content if you use SSR.
  • Race Conditions & Memory Leaks: If you don’t write a cleanup function, you could end up introducing bugs when setting state with responses that arrive in a different order or just in components that are not mounted anymore.

So, does that mean that I need a library? Well, yes. And no.

If you don’t need SSR or request caching and your app is not complex enough for waterfalls to be a problem, useEffect could be just fine. It’s not that it should get banned all of a sudden, it’s just that the React developers want you to think about how architectural choices will affect your app’s UX and performance.

Having said that, there is something you definitely need to care about if you are fetching data with useEffect, and it’s the last point in the list above: writing cleanup functions. When doing any asynchronous operation in general, make sure you ignore stale ones or abort the fetch requests with AbortController.

Ignore stale async operations:

You can use the following hook: useAsyncEffect. It encapsulates the example in React docs and works with any async operation. The ignore.current attribute will be true if the cleanup function runs, i.e., the effect is stale or the component unmounted.

From React Hooks API reference:

“If a component renders multiple times (as they typically do), the previous effect is cleaned up before executing the next effect”

Abort stale fetch requests:

The following hook is a good example: useFetchWithAbort. It’s based on the same principle as the previous one, but it’s specific to fetch requests and uses AbortController to effectively cancel the request on cleanup.

If you want to delve deeper into avoiding race conditions and memory leaks with useEffect, take a look at “Fixing Race Conditions in React with useEffect” by Max Frozen.

If you care about performance and want to know more about network waterfalls, check this out: “How to fetch data in React with performance in mind” by Nadia Makarevich.

CSS Container Queries

There are still early days for Container Queries, but with the release of Safari 16.0 last month, they are already supported in Safari (Webkit) and Chrome (Blink), which means that Edge (Blink) will follow soon. Firefox is probably not far behind either.

As you probably know, with Container Queries we can make styling choices based on the size of a container element rather than the browser size alone:

.posts {
  container-name:posts;
  container-type:inline-size;
}

.post {
  display:flex;
  flex-direction:column;
}

// This style will not apply if posts container is >= 600px
@containerposts (min-width:600px) {
  .post {
    flex-direction:row;
  }
}

But did you know that they can be much more than just container size checking? With Style Queries, you can query any of the computed CSS property values of the container, i.e., you can style children conditionally based on the container’s styles!

// If posts container has white background, make .post color gray
@containerposts (background-color:#fff) {
  .post {
    color:#444;
  }
}

Style Queries are not part of the initial Container Queries implementation that just landed in Chrome and Safari. However, they are part of the W3C CSS Containment standard and Chrome has shipped experimental support behind a feature flag.

To stay up-to-date regarding browser support and dig a little deeper on this topic, take a look at this article from Bramus or listen to the CSS Podcast Episode 59 from Una and Adam!

The Problems and Benefits of CSS-in-JS

CSS-in-JS is a new paradigm that has taken the frontend development space by storm. It has been gaining traction since component-based JavaScript frameworks like React, Vue or Angular appeared, but it has always been controversial.

For their advocates, if you use global stylesheets it can be hard to tell what the end result will look like. Due to the cascading nature of CSS, they can load in any order and override each other.

With CSS-in-JS, styles are bundled with the component. Changes to the styling of a component will not have unexpected consequences, and if a component gets deleted, so happens to their CSS styles.

However, this approach has also some important drawbacks worth taking into account, and Sam Magura wrote a great article about it: Why We’re Breaking Up with CSS-in-JS.

You’ll find a pretty detailed breakdown of benefits and drawbacks of CSS-in-JS, with benchmarks and a detailed analysis of the performance implications. Finally, he explains the solution they came up with: CSS Modules (written in SASS, in this case). A thoughtful analysis of the whole paradigm, definitely worth taking a look!

And speaking of CSS, the annual developer survey about the latest CSS trends is now open! Take the State of CSS survey here!


Anything you’d like to add? Think there is something missing? Ping us on @whitespectrehq, Instagram or LinkedIn, we’d love to read your feedback!

Let’s Chat