Developing a product catalog with filters for a mobile app is a challenge we have tackled in over 80 projects, serving clients from fashion retail to building materials. A properly implemented catalog not only displays products but also helps users quickly find the right item through filters, sorting, and switching between grid and list views. We guarantee performance even with 10,000+ SKUs and complex display logic.
The most common mistake when creating a catalog is storing filter state in the component's local state. When navigating to a product card and back, all selected parameters are reset, forcing the user to start over. According to our observations, this reduces conversion by 15–20%. Our approach: filters are stored in a global store (Zustand, Redux, Riverpod, or Bloc) and serialized into a deep link to preserve between sessions, which works more reliably than simple session state.
List performance is the second key quality criterion for a catalog. FlashList from Shopify renders long lists 5–10 times faster than the standard FlatList when dealing with 1,000+ items. FlashList — Shopify Open Source confirms that replacing FlatList with FlashList reduces time to first frame by 58–70%. On Flutter, we use CustomScrollView with SliverList and virtualization. Product images are cached via FastImage (React Native) or CachedNetworkImage (Flutter) — traffic is reduced by 40–60%.
How to Structure Filter Architecture in a Mobile App?
Filters are divided into two types: client-side (applied instantly to already loaded data) and server-side (a request is sent to the backend on each change). Client-side filters are faster and require no network requests, but are limited by the amount of data on the device. Server-side filters are necessary for catalogs with thousands of items or complex business logic: real-time warehouse stock, contractual pricing.
We implement a hybrid approach: the first page loads from the server with default parameters, subsequent pages are updated via a debounced request (300 ms) when filters change. State is serialized into URL through react-navigation or go_router, allowing users to return to the catalog with the same settings even after app restart. Users can also share a link to a specific product selection — more convenient than storing only in the device's RAM.
Which Product Catalog View Modes to Choose?
Most eCommerce apps support grid and list views. Grid is better for visual products — clothing, furniture, decor — where the buyer chooses by sight. List is more convenient for electronics or auto parts, where specifications and price matter. We recommend supporting both modes and saving the user's choice in AsyncStorage (React Native) or SharedPreferences (Android) so it persists between sessions.
| Parameter | Grid | List |
|---|---|---|
| Columns | 2–3 | 1 |
| Display focus | Image, price | Description, specifications |
| Application | Clothing, decor, cosmetics | Electronics, parts, materials |
| Scroll speed | Fast scrolling | More information per screen |
| Recommended type | Impulse purchases | Rational choice |
Performance Optimization and Technical Solutions
For smooth scrolling, memoize the product card component and separate images into preview and detail views. Pagination is built using onEndReached (React Native) or ScrollController (Flutter): when 80% of the list length is reached, the next page request is sent in advance. This makes data loading unnoticeable to the user. This approach is faster than a manual "Show more" button and more efficient than preloading all pages.
Four steps to reduce list render time:
- Replace FlatList with FlashList or use SliverList on Flutter instead of ListView.builder
- Add card memoization via React.memo or const-constructor widget
- Set up getItemType for different cell types: product, banner, separator, skeleton
- Enable removeClippedSubviews and adjust windowSize to the device screen size
| Metric | Before Optimization | After Optimization |
|---|---|---|
| FPS when scrolling 1,000 items | 30–40 | 58–60 |
| First paint time, ms | 800–1,200 | 200–400 |
| Memory consumption, MB | 180–250 | 80–120 |
| Image traffic | 100% | 40–60% |
Typical mistake: filters in component local state
When storing selected filters in useState (React Native) or StatefulWidget (Flutter), the component loses state on navigating back. The user has to reconfigure filters — according to our data, this reduces conversion by 15–25%. Solution: move filters to a global store and serialize into URL via deep link. State restoration takes less than 50 ms and is unnoticeable to the user.
What's Included in the Work
- Catalog UI: grid, list, product cards, active filter chips, and sorting
- Client-side and server-side filters with debounce, caching, and request deduplication
- Global store for filter state (Zustand, Redux Toolkit, Riverpod, Bloc)
- Filter serialization into deep link for link sharing and session restoration
- Performance optimization: FlashList or SliverList, FastImage, virtualization
- Pagination or infinite scroll with next page preloading
Timeline and Cost
A basic catalog with client-side filters takes 3–5 working days. The full version with server integration, filter persistence, offline cache, and two view modes takes 8 to 12 working days. Cost starts from $800 for an MVP and from $2,000 for a full-featured solution. We provide a free estimate after analyzing your requirements. Contact us for a consultation and receive an accurate timeline and budget.
Our experience in over 80 mobile catalog development projects allows us to guarantee results: list performance, filtering convenience, and stable operation when scaling assortment. We work with clients from Russia, Belarus, and Israel, and select the stack to fit your existing infrastructure. Each project is accompanied by documentation, access transfer, and post-launch support.







