CSS Only* Search: Improve React Filtering Performance with CSS!

Rate this content
Bookmark

Working on emoji-picker-react I encountered a challenge - filtering the list of 1800 emojis triggered a significant delay due to re-renders.

Let's learn how I fixed this only using CSS!

This talk has been presented at React Day Berlin 2023, check out the latest edition of this React Conference.

Watch video on a separate page

FAQ

Evitar Alus is a frontend engineer at Meda in Tel Aviv and the author of several open source packages, including emoji-pkreact for React applications.

The emoji-pkreact package is an open-source component designed by Evitar Alus that allows easy integration of emojis into React web applications.

Initially, the emoji-pkreact had performance issues with laggy search functionality due to the rendering and state updating of approximately 1800 emojis.

Evitar Alus enhanced the search performance by using CSS attribute selectors for filtering emojis based on their names, reducing the need to manipulate the DOM extensively for each search input.

The CSS 'Has' pseudo-selector checks for certain conditions within a selector's children. In emoji-pkreact, it is used to hide emoji categories dynamically if they do not contain any emojis matching the search query.

The updated search mechanism in emoji-pkreact shows almost no delay even on low-end machines, significantly improving performance by minimizing DOM updates and relying on CSS for display changes.

After implementing the new search feature, profiler tests indicated that the only significant update during a search operation was to the search bar, confirming reduced impact on overall application performance.

Evyatar Alush
Evyatar Alush
11 min
12 Dec, 2023

Comments

Sign in or register to post your comment.
Video Summary and Transcription
Evitar Alus, a frontend engineer, shares a trick to improve search performance in React applications by optimizing the search algorithm and reducing DOM updates. CSS attribute selectors can be used for filtering and applying styles based on emoji values. A component called CSS Search can be created to improve search performance by hiding emojis that do not match the search query. Despite some performance drawbacks, this solution works significantly faster. Visit Evitar Alus' website or Twitter account for more of their work.

1. Improving Search Performance in React Applications

Short description:

I'm Evitar Alus, a frontend engineer at Meda in Tel Aviv and the author of the open source package emoji-pkreact. I want to share a trick to improve search performance in React applications. Initially, I faced performance issues due to the large number of emojis and the complex state management. The search bar and emojis were distant in the React tree, causing delays. I made improvements to the search algorithm and reduced the DOM updates, resulting in faster performance. Let me show you the difference and explain how I achieved it.

Hey, everybody. How are you? My name is Evitar Alus. I'm a frontend engineer at Meda in Tel Aviv and I'm the author of several open source packages, one of which is this cool little package called emoji-pkreact that allows you to put an emoji-pkreact right inside your React application on the web with ease.

And today I want to share with you a little trick that I came up with to improve search performance in React applications and React packages. And when I started building emoji-pkreact back in 2017-ish, I thought it would be pretty straightforward to build an emoji-pkreact component with all the features of an expected emoji-pkreact that would also be performant and easy to use. And quite immediately I started receiving issues about performance, for example, that search is extremely laggy and, obviously, my response was that it does not reproduce. Obviously, that was wrong.

Search was actually laggy. And the reason for it is quite understandable. You see, we have roughly 1800 different emojis being rendered on the Emoji Picker. And when you interact with each of them, you have some state updates. So, for example, when you hover or when you type something in the search, you make changes to the DOM and to the elements. And when you deal with so many elements, and when they have so many different states that they can be in, it can be quite intense to work with. And especially here, we see the search bar is up here and the emojis are there. Which means that they're very distant in the React tree. Which means that we have to have some almost global Emoji Picker React state to manage the filtering capabilities. And then when we type some character inside of the Emoji Picker, we go update the state, run some search algorithm that I try to make performant, and then React goes and does DOM diffing and then only applies the changes to the DOM, and each of these steps take time. And when we deal with 1800 emojis, that takes a lot of time.

Now, if you look now, it looks pretty immediate. It works pretty fast, but I want to show you just for a second what it felt like before Emoji Picker React had these capabilities and the improved search. So I'll type something and you'll notice slight lag, even on my MacBook Pro. You felt that? There was some lag between my character being typed and the changes appearing on a screen, and that's a high-end MacBook Pro. Let's try to do some slowdowns, so 6x slowdown to simulate an older machine, or a slower machine, and let's see what it actually feels like for a user in the wild. And you saw that, right? That's not ideal. We gotta fix this. Just to show you what actually is going on when we type each character, when we type each character, we actually go out and re-render everything. And the reason is, again, that we have that top level tree as state and that we actually have to modify all the elements on the DOM. But do we, really? And this is what I wanted to find out. Do I really have to manipulate the DOM and change all the emojis just to make them disappear? Or maybe I can somehow skip it? So I went to look at the actual emoji elements that I created and what I have here, each emoji is a button component or a button element and they have an image inside them. They sometimes have a span with an emoji character.

2. Using CSS Attribute Selectors for Filtering

Short description:

It depends on the user configuration. Each emoji has an area label and full name for accessibility and search. We can use CSS attribute selectors to apply styles based on these values. Let's update our search component to use local state instead of the global state. By setting a value, we can apply filters to the emoji picker.

It depends on the user configuration. But each of them has an area label for accessibility, and also the full name for the emoji of the emoji, because an emoji might have multiple names for search. And given the fact that I already have all this information on the DOM, maybe I can make use of it for filtering as well? Apparently I can and apparently it's pretty easy.

In CSS we have something that's called an attribute selector that allows us to select an arbitrary attribute and based on its value apply styles to elements. So this means that I can set a selector based on the full name, the data property or based on the area label. And I just want to show you how it's done and how easy it is to actually implement.

So here is our search component. It works currently by updating the global state but instead let's not do that anymore. And instead let's have some local states. So let's import useState. So import useState from React and then let's set this state. So const value setValue equals useState. It should be undefined and also let's initialize it to undefined or string. Yeah, cool. And now all we have to do here is set a value and if we'll look back at the emoji picker we'll see that typing does not do anything other than just hide the categories. And the reason is because we do not apply anything from it yet.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Build a Design System with React and Tailwind CSS
React Summit 2022React Summit 2022
27 min
Build a Design System with React and Tailwind CSS
Top Content
This Talk discusses design systems and how to build one using React and Tailwind CSS. Tailwind CSS provides utility classes for building complex layouts without writing CSS rules. Custom colors can be added to the Tailwind CSS config file, and font styles and text sizes can be customized. The entire Tailwind CSS configuration can be customized to meet specific requirements. Base styles can be added to the config file itself using a plugin. Reusable components can be created with Tailwind CSS, allowing for easy customization of size and color.
Rethinking CSS - Introducing Stylex
React Finland 2021React Finland 2021
25 min
Rethinking CSS - Introducing Stylex
Top Content
CSS + superpowers - bloat. How Stylex creates a zero-cost abstraction that gives CSS superpowers.
How to achieve layout composition in React
React Summit 2022React Summit 2022
8 min
How to achieve layout composition in React
This talk discusses achieving layout composition in React using Bedrock Layout Primitives. By componentizing CSS layout, complex layouts can be achieved and reused across different components. The talk also covers the challenges of achieving complex layouts, such as card lineups, and provides solutions for maintaining alignment and responsiveness. The BedrockLayout primitive library simplifies web layouts and offers flexibility in composing layouts.
Type-safe Styling for React Component Packages: Vanilla Extract CSS
React Advanced 2023React Advanced 2023
19 min
Type-safe Styling for React Component Packages: Vanilla Extract CSS
Watch video: Type-safe Styling for React Component Packages: Vanilla Extract CSS
Today's Talk introduces Vanilla Extract CSS, a type-safe styling method for React applications. It combines the benefits of scoped styling, zero runtime overhead, and a great developer experience. Vanilla Extract generates a static CSS file at build time, resulting in better performance. It is framework agnostic and offers a powerful toolkit, including Sprinkles for utility classes and CSS utils for calculations. With type safety and the ability to define themes and variants, Vanilla Extract makes it easy to create efficient, scalable, and maintainable design system component packages.
Moving on From Runtime Css-In-Js at Scale
React Summit 2023React Summit 2023
29 min
Moving on From Runtime Css-In-Js at Scale
Watch video: Moving on From Runtime Css-In-Js at Scale
This Talk explores the evolution of styling architecture, dynamic theming with style components, and optimizing style updates. It discusses the challenges of CSS migration and the choice between JavaScript and CSS native tooling. The Talk also touches on CSS tools and libraries, including Tailwind CSS and CSS in JS major libraries like MUI. The importance of picking a stack based on team members' strengths and the use of namespacing CSS for conflict-free dependency trees are highlighted.
Building Pixel-Perfect UI Components Using CSS Variables
React Summit 2023React Summit 2023
9 min
Building Pixel-Perfect UI Components Using CSS Variables
Watch video: Building Pixel-Perfect UI Components Using CSS Variables
CSS variables and their possibilities for UI developers, MUI's history and understanding of developer needs, Joy UI's focus on developer experience and use of CSS variables for consistency and future-proofing, the elimination of manual calculations and JavaScript with CSS variables in JoyUI, and the availability of playgrounds and a stable release for exploration.

Workshops on related topic