GeistHaus
log in · sign up

https://medium.com/feed/dailyjs

rss
40 posts
Polling state
Status active
Last polled May 18, 2026 21:25 UTC
Next poll May 19, 2026 19:43 UTC
Poll interval 86400s

Posts

Applying SOLID principles in React
reactbest-practicesprogramming
Show full content
Photo by Jeff Nissen on Unsplash

As the software industry grows and makes mistakes, the best practices and good software design principles emerge and conceptualize to avoid repeating the same mistakes in the future. The world of object-oriented programming (OOP) in particular is a goldmine of such best practices, and SOLID is unquestionably one of the more influential ones.

SOLID is an acronym, where each letter represents one out of five design principles which are:

  • Single responsibility principle (SRP)
  • Open-closed principle (OCP)
  • Liskov substitution principle (LSP)
  • Interface segregation principle (ISP)
  • Dependency inversion principle (DIP)

In this article, we’ll talk about the importance of each principle and see how we can apply the learnings from SOLID in React applications.

Before we begin though, there’s a big caveat. SOLID principles were conceived and outlined with object-oriented programming language in mind. These principles and their explanation heavily rely on concepts of classes and interfaces, while JS doesn’t really have either. What we often think of as “classes” in JS are merely class look-alikes simulated using its prototype system, and interfaces aren’t part of the language at all (although the addition of TypeScript does help a bit). Even more, the way we write modern React code is far from being object-oriented — if anything, it feels more functional.

The good news though, software design principles such as SOLID are language agnostic and have a high level of abstraction, meaning that if we squint hard enough and take some liberties with interpretation, we’ll be able to apply them to our more functional React code.

So let’s take some liberties.

Single responsibility principle (SRP)

The original definition states that “every class should have only one responsibility”, a.k.a. do exactly one thing. We can simply extrapolate the definition to “every function/module/component should do exactly one thing”, but to understand what “one thing” means we’ll need to examine our components from two different perspectives — internal (meaning what the component does inside) and external (how this component is used by other components).

We’ll start by looking from the inside. To ensure our components do one thing internally, we can:

  • break large components that do too much into smaller components
  • extract code unrelated to the main component functionality into separate utility functions
  • encapsulate connected functionality into custom hooks

Now let’s see how we can apply this principle. We’ll start by considering the following example component that displays a list of active users:

Although this component is relatively short now, it is already doing quite a few things — it fetches data, filters it, renders the component itself as well as individual list items. Let’s see how we can break it down.

First of all, whenever we have connected useState and useEffect hooks, it's a good opportunity to extract them into a custom hook:

Now our useUsers hook is concerned with one thing only - fetching users from API. It also made our main component more readable, not only because it got shorter, but also because we replaced the structural hooks that you needed to decipher the purpose of with a domain hook the purpose of which is immediately obvious from its name.

Next, let’s look at the JSX that our component renders. Whenever we have a loop mapping over an array of objects, we should pay attention to the complexity of JSX it produces for individual array items. If it’s a one-liner that doesn’t have any event handlers attached to it, it’s totally fine to keep it inline, but for a more complex markup it could be a good idea to extract it into a separate component:

Just as with a previous change, we made our main component smaller and more readable by extracting the logic for rendering user items into a separate component.

Finally, we have the logic for filtering out inactive users from the list of all users we get from an API. This logic is relatively isolated and it could be reused in other parts of the application, so we can easily extract it into a utility function:

At this point, our main component is short and straightforward enough that we can stop breaking it down and call it a day. However, if we look a bit closer, we’ll notice that it’s still doing more than it should. Currently, our component is fetching data and then applying filtering to it, but ideally, we’d just want to get the data and render it, without any additional manipulation. So as the last improvement, we can encapsulate this logic into a new custom hook:

Here we created useActiveUsers hook to take care of fetching and filtering logic (we also memoized filtered data for good measures), while our main component is left to do the bare minimum - render the data it gets from the hook.

Now depending on our interpretation of “one thing”, we can argue that the component is still first getting the data, and then rendering it, which is not “one thing”. We could split it even further, calling a hook in one component and then passing the result to another one as props, but I found very few cases where this is actually beneficial in real-world applications, so let’s be forgiving with the definition and accept “rendering data the component gets” as “one thing”.

Now for the external perspective. Our components never exist in isolation, instead, they’re a part of a larger system in which they interact by either providing their functionality to other components, or consuming functionality provided by other components. As such, the external view of SRP is concerned with how many things a component can be used for.

To understand it better, let’s consider the following example. Imagine a messaging app (like Telegram or FB Messenger) and a component that displays a single message. It can be as simple as this:

If we want to send images together with text, the component becomes a bit more complex:

Going further, we can add support for voice messages as well, which will further complicate the component:

It’s not difficult to imagine how, as time goes on and we add support for videos, stickers, etc., this component will keep growing and turn into a giant mess. Let’s recap what’s happening here.

At the start, our component complies with SRP and it does exactly one thing — it renders a message. However, as the application evolves, we gradually add more and more functionality to it. We start with small conditional changes in render logic, then go more aggressively completely replacing the render tree, and somewhere along the way the original definition of “one thing” for this component becomes too broad, too generic. We start with a single-purpose component and end up with a multipurpose do-it-all kind.

The way to solve this problem is to get rid of the generic Message component in favor of more specialized, single-purpose components:

The logic inside these components is very different from one another, so it’s natural for them to evolve separately.

It should be said that problems like this always creep in gradually as the application grows. You want to reuse an existing component/function that does almost everything you need, so you throw in an extra prop/argument and adjust the logic inside accordingly. Next time, somebody else ends up in the same situation, and instead of creating separate components and extracting shared logic, they add another argument and another if. The snowball keeps growing.

To break out of this loop, next time you’re about to adjust an existing component to fit your case, consider whether you’re doing it because it makes sense and it will make the component more reusable, or because you’re just being lazy. Beware of the problem of universal components and pay attention to how you define what its single responsibility is.

On a practical side, a good indication that a component has outgrown its original purpose and requires splitting is a bunch of ifstatements changing the behavior of the component. It applies to plain JS functions as well — if you keep adding arguments that control the execution flow inside a function to produce different results, you might be looking at a function that’s doing too much. Another sign is a component with a lot of optional props. If you use such a component by supplying a distinct subset of properties in different contexts, chances are you deal with multiple components masquerading as one.

To summarize, the single-responsibility principle is concerned with keeping our components small and single purpose. Such components are easier to reason about, easier to test and modify, and we’re less likely to introduce unintentional code duplication.

Open-closed principle (OCP)

OCP states that “software entities should be open for extension, but closed for modification”. Since our React components and functions are software entities, we don’t need to bend the definition at all, and instead, we can take it in its original form.

The open-closed principle advocates for structuring our components in a way that allows them to be extended without changing their original source code. To see it in action, let’s consider the following scenario — we’re working on an application that uses a shared Header component on different pages, and depending on the page we're at, Header should render a slightly different UI:

Here we render links to different page components depending on the current page we’re at. It’s easy to realize that this implementation is bad if we think about what will happen when we start adding more pages. Every time a new page is created, we’ll need to go back to our Header component and adjust its implementation to make sure it knows which action link to render. Such an approach makes our Header component fragile and tightly coupled to the context in which it's used, and it goes against the open-closed principle.

To fix this problem, we can use component composition. Our Header component doesn’t need to concern itself with what it will render inside, and instead, it can delegate this responsibility to the components that will use it using children prop:

With this approach, we completely remove the variable logic that we had inside of the Header and now can use composition to put there literally anything we want without modifying the component itself. A good way of thinking about it is that we provide a placeholder in the component that we can plug into. And we're not limited to one placeholder per component either - if we need to have multiple extension points (or if the children prop is already used for a different purpose), we can use any number of props instead. If we need to pass some context from the Header to components that use it, we can use the render props pattern. As you can see, composition can be very powerful.

Following the open-closed principle, we can reduce coupling between the components, and make them more extensible and reusable.

Liskov substitution principle (LSP)

LSP recommends designing objects in such a way that “subtype objects should be substitutable for supertype objects”. In its original definition, the subtype/supertype relationship is achieved via class inheritance, but it doesn’t have to be that way. In a broader sense, inheritance is simply basing one object upon another object while retaining a similar implementation, and this is something we do in React quite often.

A very basic example of a subtype/supertype relationship could be demonstrated with a component built with styled-components library (or any other CSS-in-JS library that uses similar syntax):

In the code above, we create StyledButton based on Button component. This new StyledButton component adds a few CSS classes but it retains the implementation of the original Button, so, in this context, we can think of our Button and StyledButton as supertype and subtype components.

Additionally, StyledButton also conforms to the interface of the component it’s based on - it takes the same props as Button itself. Because of that, we can easily swap StyledButton for Button anywhere in our application without breaking it or needing to make any additional changes. That’s the benefit we get by conforming to the Liskov substitution principle.

Here’s a more interesting example of basing one component on another:

In the code above, we use a basic Input component to create an enhanced version of it that can also display the number of characters in the input. Although we add new logic to it, CharCountInput still retains the functionality of the original Input component. The interface of the component also remains unchanged (both inputs take the same props), so LSP is observed again.

Liskov substitution principle is particularly useful in the context of components sharing common traits, such as icons or inputs — one icon component should be swappable for another icon, more specific DatePickerInput and AutocompleteInput components should be swappable for a more generic Input component, and so on. However, we should acknowledge that this principle cannot and should not always be observed. More often than not, we create sub-components with the goal of adding new functionality that their super-components don’t have, and that will often break the interface of the super-component. This is a completely valid use case, and we shouldn’t try to shoehorn LSP everywhere.

As for components where LSP does make sense, we need to make sure that we don’t break the principle unnecessarily. Let’s take a look at two common ways in which it may happen.

The first one involves cutting off a part of props without a reason:

Here, we redefine props for CustomInput instead of using props that <input /> expects. As a result, we lose a large subset of properties that <input /> can take thus breaking its interface. To fix that, we should use the props that the original <input /> expects and pass them all down using a spread operator:

Another way to break LSP is to use aliases for some of the properties. This may happen when the property we want to use has a naming conflict with a local variable:

To avoid such conflicts, you want to have a good naming convention for your local variables. For example, it’s common to have a matching handleSomething local function for every onSomething property:

Interface segregation principle (ISP)

According to ISP, “clients should not depend upon interfaces that they don’t use.” For the sake of React applications, we’ll translate it into “components shouldn’t depend on props that they don’t use”.

We’re stretching the definition of the ISP here, but it’s not a big stretch — both props and interfaces can be defined as contracts between the object (component) and the outside world (the context in which it’s used), so we can draw parallels between the two. In the end, it’s not about being strict and unyielding with the definitions, but about applying generic principles in order to solve a problem.

To better illustrate the problem ISP is targeting, we’ll use TypeScript for the next example. Let’s consider the application that renders a list of videos:

Our Thumbnail component that it uses for each item might look something like this:

The Thumbnail component is quite small and simple, but it has one problem - it expects a full video object to be passed in as props, while effectively using only one of its properties.

To see why that’s problematic, imagine that in addition to videos, we decide to display thumbnails for live streams as well, with both kinds of media resources mixed in the same list.

We’ll introduce a new type defining a live stream object:

And this is our updated VideoList component:

As you can see, here we have a problem. We can easily distinguish between video and live stream objects, but we cannot pass the latter to the Thumbnail component because Video and LiveStream are incompatible. First, they have different types, so TypeScript would immediately complain. Second, they contain the thumbnail URL under different properties - video object calls it coverUrl, live stream object calls it previewUrl. That's the crux of the problem with having components depend on more props than they actually need - they become less reusable. So let's fix it.

We’ll refactor our Thumbnail component to make sure it relies only on props it requires:

With this change, now we can use it for rendering thumbnails of both videos and live streams:

The interface segregation principle advocates for minimizing dependencies between the components of the system, making them less coupled and thus more reusable.

Dependency inversion principle (DIP)

The dependency inversion principle states that “one should depend upon abstractions, not concretions”. In other words, one component shouldn’t directly depend on another component, but rather they both should depend on some common abstraction. Here, “component” refers to any part of our application, be that a React component, a utility function, a module, or a 3rd party library. This principle might be difficult to grasp in the abstract, so let’s jump straight into an example.

Below we have LoginForm component that sends user credentials to some API when the form is submitted:

In this piece of code, our LoginForm component directly references the api module, so there's a tight coupling between them. This is bad because such dependency makes it more challenging to make changes in our code, as a change in one component will impact other components. The dependency inversion principle advocates for breaking such coupling, so let's see how we can achieve that.

First, we’re going to remove direct reference to the api module from inside the LoginForm, and instead, allow for the required functionality to be injected via props:

With this change, our LoginForm component no longer depends on the api module. The logic for submitting credentials to the API is abstracted away via onSubmit callback, and now it is the responsibility of the parent component to provide the concrete implementation of this logic.

To do that, we’ll create a connected version of the LoginForm that will delegate form submission logic to the api module:

ConnectedLoginForm component serves as a glue between the api and LoginForm, while they themselves remain fully independent of each other. We can iterate on them and test them in isolation without worrying about breaking dependent moving pieces as there are none. And as long as both LoginForm and api adhere to the agreed common abstraction, the application as a whole will continue working as expected.

In the past, this approach of creating “dumb” presentational components and then injecting logic into them was also used by many 3rd party libraries. The most well-known example of it is Redux, which would bind callback props in the components to dispatch functions using connect higher-order component (HOC). With the introduction of hooks this approach became somewhat less relevant, but injecting logic via HOCs still has utility in React applications.

To conclude, the dependency inversion principle aims to minimize coupling between different components of the application. As you’ve probably noticed, minimizing is somewhat of a recurring theme throughout all SOLID principles — from minimizing the scope of responsibilities for individual components to minimizing cross-component awareness and dependencies between them.

Conclusion

Despite being born out of problems of the OOP world, SOLID principles have their application well beyond it. In this article, we’ve seen how by having some flexibility with interpretations of these principles, we managed to apply them to our React code and make it more maintainable and robust.

It’s important to remember though, that being dogmatic and religiously following these principles may be damaging and lead to over-engineered code, so we should learn to recognize when further decomposition or decoupling of components stands to introduce complexity for little to no benefit.

Originally published at https://konstantinlebedev.com.


Applying SOLID principles in React was originally published in DailyJS on Medium, where people are continuing the conversation by highlighting and responding to this story.

https://medium.com/p/14905d9c5377
Extensions
Low-Code Solutions for Building Basic SaaS Features
software-developmenttechnologysaas
Show full content
Photo by Danist Soh from Unsplash

Nowadays, you can easily build a new business using a SaaS application and seize opportunities in new emerging markets. Various SaaS applications serve different purposes and for different kinds of users or target users.

To build a SaaS application, you need to have experience in software or web development or hire a software engineer, which can be very expensive. It is best to hire if the application is complex or if you don’t have the needed experience.

However, if you want to do it yourself, one way is learning how to code. This is a slow process. It takes months before you can even grasp concepts and build a basic app. The second option is to use no-code, low-code, or visual programming solutions.

If you are a developer and you want to get things done faster, you can also use low-code solutions, which will speed up the development process.

Basic SaaS FeaturesAuthentication and Authorization

In every basic SaaS application, authentication and authorization are two key features that need to be available, especially if it’s a web application.

In most standard applications, users need to create an account and log in anytime they want to use it. This helps the application serve them better by saving their progress, keeping a record of everything carried out on the app, or customizing the app based on their profile, settings, and usage.

Let’s say our web application is a note-taking app. Users need to create an account and log in to save their notes and retrieve them anytime they need them.

To enable authentication on your application, users need to be able to create an account using a username/email and password. Then, authorization is required if you want to limit what a particular user can access.

User and Role Management

User management is how administrators manage users on their platform — it gives them visibility of users on their platform. Managing users and their roles is very important in an application. Users should be able to access only what they are required to.

Having two types of users with different roles in an application helps you manage the different features and access each type of user needs.

Subscription and Payments

To keep the services running and pay for the resources used in the application, you need to accept some form of payment.

There are many ways to add payments to your application. However, you will need to figure out which country your target users reside in and their method of payment — you need to integrate a payment gateway that can accept most payment methods for your target users.

There are tons of payment gateways these days, which makes it easier for you to integrate a payment system on your application and accept payments easily. Some gateways make it easier by providing Checkout UI, Payment SDK, and payment buttons to make the process easier.

Webhooks and Events

When building a SaaS application that deals with a lot of asynchronous data from different external services, you need to find a way to listen and react when something happens in the system.

Webhooks and events allow you to listen to all the events in the system and react to them. For example, let’s say we want to be able to generate custom invoices for user payments. We’ll need to listen to Stripe events to know when the user pays and generate a custom invoice for the user.

Once the invoice is generated, we’ll want to be notified of this and automate sending the invoice to their email.

Admin Panel/Dashboard

To manage your application users, payments, and subscriptions, you will need an admin panel. With your admin access, you need to be able to:

  1. See user information
  2. Update user information
  3. Ban, deactivate, or delete user information
  4. See all their payments and subscriptions
  5. See their usage and activities

This will give you better insight into who your users are and how they are using your platform.

Your admin panel can have features to give discounts/bonuses to users, refund users, manage payments, and so on.

Solutions

So far, we have looked at some basic SaaS features. Now let’s look at their solutions.

Frontegg

Frontegg is a user management platform that lets you embed a drop-in authentication, authorization, user, and role management at a go. And you don’t have to write any code. It provides all the building blocks to add authentication and user management to your application. It gives you the self-service admin experience with a multi-tenant feature to manage all your users, their roles and permissions, payments, and subscriptions in different applications.

Out of the box, Frontegg will let you set pricing for your users. Your users can choose subscription plans, change plans, and automate renewal. Frontegg provides a way to listen to all the events happening in your system. The best advantage of Frontegg is you don’t need to write any code to implement it. You can just embed it in your admin interface — you can also get started for free to test their most popular features at a smaller scale.

Zapier

Zapier is an automation platform that lets you create zaps with webhooks and react to the incoming data payload. With Zapier, you can handle the whole application background operations using its large arrays of integrations. This includes the database, emails, HTTP requests, and so on.

It is a very useful product if your app involves some automation in dynamic forms, payments, and subscriptions. If your app interacts with lots of external services that have already been integrated with Zapier, you can easily use Zapier to communicate.

Auth0

Auth0 is simply an authentication and authorization platform that can be added to any application to enable auth services. It provides the building blocks for developers to build on authentication services into their applications. With Auth0, you still need to perform a significant amount of coding to make it work seamlessly in your application. Therefore, it is ideal for developers who don’t want to waste time building auth from scratch.

Retool

Retool is a simple drag and drop platform that helps you build internal tools and dynamic dashboards and connect them to your databases, APIs, and other services like Google Cloud Platforms services. Retool also lets you write custom SQL queries and Javascript so you can interact with data and handle the app interactions.

With Retool, you can build a custom dashboard that shows all your users in your database and lets you update your users’ roles directly from the dashboard. However, you still need to write some code at the frontend app to handle the app interaction. You will also need to design the app and connect it to the database using the UI toolkit.

Stripe

Stripe provides you with out-of-the-box tools to easily accept payments on your application and customize the checkout UI and payment button without writing a single line of code. So if you are not a developer, you can still integrate Stripe on your application by just embedding the payment buttons and checkout on your application.

Stripe also lets you manage your user subscriptions. If you are offering a subscription pricing model, you can use Stripe to easily manage all your users’ subscriptions and give access to the right people.

Stripe also lets you create coupon codes so you can give discounts to your users anytime.

Conclusion

I wish we could explore more solutions as there are tons of low-code solutions that provide various benefits. Your choice of solution should depend on your usage — what works best for you and lets you achieve your app goals.


Low-Code Solutions for Building Basic SaaS Features was originally published in DailyJS on Medium, where people are continuing the conversation by highlighting and responding to this story.

https://medium.com/p/aa71c087a753
Extensions
Three Practical Examples of Concurrent React
javascriptreactfront-end-developmentuxweb-development
Show full content
Optimizing Performance using React 18 startTransition API

The React team recently announced the plan for React 18, bringing a lot of cool new features like automatic batching, new suspense SSR Architecture, and new APIs that leverage concurrent rendering like the startTransition API.

For the past few years, the React team has been working on major features that will support concurrent rendering, those features are going to have a remarkable effect on both the user experience and the development process.

There are a lot of resources where you can learn more about concurrent React, so I’ll not cover how it works behind the scenes in depth. Instead, I’ll show you three practical use-cases where I leveraged the new React startTransitionAPI to resolve major performance issues.

Disclaimer:
At the time of writing this post, React 18 is still in Alpha. You are more than welcome to explore it and play with it, but it’s not yet stable and ready for production usage.
In addition, all of the examples in this post are presented using Codesandbox which has a performance overhead because it runs in development mode. For the most realistic results, you can run the examples in this repo in production mode.
A few words about the React startTransition API

The new React startTransition API will help make your application more responsive, even during large screen updates. With this new API, you can substantially improve user interactions by marking specific updates as “transitions.” React will let you provide visual feedback during a state transition and keep the browser responsive while the transition is in progress.

Use case#1 — Searching for Pokemon

I love Pokemon.

That’s why I’ve decided to build a small screen where I can search for all the Pokemon in the world and get some details about them. There are a lot of Pokemon out there and I didn’t want to start messing with DOM virtualization techniques. I decided I just “Gotta render em all.”
That list happened to be quite big, and the search input felt a bit laggy.

Let me give you a live demonstration:

If you are working on the average computer, you probably noticed the delay while typing. If you didn’t, let me help you get off your high horse with the following trick ;)

  • Open the developer console
  • Click performance
  • Change CPU throttling to 4x slowdown

Now for sure, you’ll notice the delay. This is not the optimal user experience.
Input typing is a sensitive UX action. The user is focused on the input while typing in it, and is expecting to get very quick feedback from the app that whatever is typed on the keyboard is displayed in that input.

Think about yourself as a user: isn’t it frustrating that you type something and don’t see those letters being painted until after a half-second? It immediately makes you think, “Argh, this app is so slow!”
It’s very important to render those UX-sensitive actions as fast as we can, and give quick feedback to the user.

Now, let’s have a look at the code:

Why is the search so laggy?

The reason for the lagginess is because we render A LOT of pokemons on each keypress. We have around 1300 pokemons at the initial render. Let’s assume we press ‘b’; after pressing this key, React recalculates all the changes against the old DOM representation, and commits those changes to the DOM accordingly. If it’s dealing with around 1300 elements, rendering takes time.
While React renders the new state to the DOM, interaction with the UI is completely blocked. You can’t do anything, can’t click the buttons, can’t see the “balbasuer” that you’ve just typed. Only after it finishes the rendering does the UI become fully responsive.

What can we do about it?

We all know that it’s a common standard to “throttle” the input’s onChange calls. That makes it call only after a specified maximum frequency, but as stated in this wonderful doc from React:

on lower-powered devices, we’d still end up with a stutter. Both debouncing and throttling create a suboptimal user experience.

And this is where React’s new startTransition API comes into the picture.
With concurrent React, the browser can work on several state updates concurrently.
By using the startTransition API, we can tell React:

“Hey React, listen, I know you want to update this list, but right now, rendering whatever the user is typing is way more important than updating that list. PLEASE stop rendering the list for a while and focus on rendering the new key the user has just pressed! You can come back to the list later.”

It’s all about prioritization.

Leveraging concurrent React for our example

We will help React mark what is less important to render, and thus help React prioritize things.

We will make the following changes:

  • Use the newReactDOM.createRoot instead of ReactDOM.render, this is part of the upgrading process to React 18 and it will prevent console warnings.
  • Split the text state into two different states, one for the input and one for the query: textand searchQuery.
  • We will use the useTransition hook that will provide us access to two important variables: startTransition and isPending.
    startTransition is a function that we will use to tell React which renders are “less important.” isPending is a boolean that tells us whether our list is pending to be rendered or not.
  • We will wrap the setSearchQuery statement with startTransition.
  • We will pass to PokemonsCard the searchQuery state instead of the text state.
  • We need to wrap our pokemon list with a React.memo. (more on that here) Since React renders all the children of a parent, setText(e.target.value) will cause a rerender of the list on each keypress, so we want the list to be controlled only by the searchQuery state.
  • We will use the isPending state to show a nice, elegant loader near the search input that shows that the list is waiting to be rendered.

Switch to ReactDOM.createRoot in our index.js file:

And our modified components:

Drum roll please… And the result

Magical, isn’t it?
Now React knows that rendering the user input is more important than rendering that list, and the user experience feels a lot more smooth and natural.

From here on I’ll speed things a bit up: I’ll just show “before” and “after” examples. There is no need to dig into details since the principle is the same among all of the examples. You are more than welcome to open the code and drill into things :)

Use case#2 — Apple stock

I like Apple, and also the stock market.

That’s why I’ve decided to build a small screen where I can view Apple’s stock over the years, watching for different trends. I’ve used the wonderful BrushChart from AirBnb’s great visualization library: visx.

* Notice that there’s a list below the chart that gets filtered according to the chart.

Play with that a bit.
Change the CPU throttling and play with that again.
Do you notice how the slider stutters?

This is the code:

The problem here is much the same as the pokemon search issue. We change the slider, which causes a rerender of a huge amount of data, which blocks further user slider changes to be painted.

Let’s apply a similar change here as well. We will wrap the setStock statement with the startTransition function:

The result:Use case#3 — Navigation

I love Pokemon. I like Apple and the stock market.

Why not build a screen where I can navigate between the two of them?

Same drill — play with it.
Did you notice the delay when you clicked the “APPLE STOCK” tab?
From the moment we click that tab, it takes some time for the tab to be highlighted. Again, this is a UX senstive action — that is, users want to get immediate feedback for clicking that tab while they are looking at it. Once they click that tab, we want to highlight it as fast as we can.
There’s a delay because React renders the long stock list once we click that tab, blocking the highlight from being painted.

Let’s tell React, “The initial render of that list is less important than highlighting the active tab!”

We change the useEffect of the stock component from this:

to this:

The result:Summary

For all of the examples I’ve just shown you, there are surely other ways to mitigate them, like virtualization, lazy loading, or even simple solutions like throttling. Still, the React team has supplied us with a built-in mechanism for concurrent renders, a mechanism that no other frontend library has built yet.

Built by the magicians at Facebook, the powerful React concurrent features enrich us with powerful tools that help us shape UX optimal applications and services optimize performance.

All the examples in this post can be found on Github, or on Codesandbox.

If you enjoyed this post, make sure to follow me on:

Medium: medium.com/@eilonmor1
Github:
github.com/eilonmore
LinkedIn:
linkedin.com/in/eilon-mor-990736150
Twitter:
twitter.com/moreilon


Three Practical Examples of Concurrent React was originally published in DailyJS on Medium, where people are continuing the conversation by highlighting and responding to this story.

https://medium.com/p/b2dba2272a4d
Extensions