Your Sunday, upgraded. Free live AI class · 5 PM ISTReserve your seat
FRONTEND & UX

React Data Flow in Practice: Build a Filterable Course Catalogue

A searchable, filterable list is one of the most common React features and a good test of how you handle state. This guide builds a course catalogue step by step and explains each decision about state, derived data, URLs and performance.

On this page

The feature

Learners should be able to search courses by text, filter by category and level, sort the results and share a link that reopens the same view. The catalogue has a few hundred items delivered with the page. The challenge is less about any single component and more about deciding where each piece of state lives and what can be derived.

Identify the minimal state

List everything that changes on screen: the search text, the selected category, the selected level, the sort order, the filtered results and the result count. Only the first four are independent choices made by the user. The results and the count can be calculated from the course list plus those four values, so they should not be stored as state at all.

Keeping state minimal removes a whole category of bugs where two copies of the same information disagree.

Place state with its owner

The filter controls and the results list are siblings, so their shared state belongs in the parent Catalogue component. The controls receive current values and callbacks such as onQueryChange; the list receives the derived results. Nothing outside the catalogue needs these values, so there is no reason for global state or context.

const visible = useMemo(
  () => sortCourses(filterCourses(courses, filters), filters.sort),
  [courses, filters],
);

Use useMemo only if filtering is measurably slow; for a few hundred items a direct calculation during render is usually fine.

Put shareable state in the URL

For links to reopen the same view, store the filters in the query string. Read them when the component first renders and update the URL with history.replaceState, or your router's equivalent, when they change. Use replace rather than push for each keystroke so the back button is not filled with intermediate searches. Validate values read from the URL, because users can edit them; unknown categories should fall back to 'all'.

This also improves accessibility and support: a learner can send the exact view they are seeing.

Keep typing responsive

Filtering on every keystroke is fine for small lists. As the list grows, three techniques help: precompute a lowercase search string for each course once, render only the first page of results with a 'Show more' button, and use React's useDeferredValue so typing stays responsive while the results update just behind it. Measure with the React Profiler before and after so you know the change helped.

Handle empty and loading states

When no course matches, explain why and offer a way out: show the active filters and a 'Clear filters' button. Announce result-count changes to screen-reader users with a polite live region. If the course list loads asynchronously, show a skeleton with the same layout rather than an empty grid that jumps when data arrives.

Test the behaviour, not the implementation

Write tests that interact like a learner: type into the search box, choose a category and assert on the visible course titles and the count. Add a test that renders the catalogue with a query string and checks the filters are restored. Tests written this way survive refactors because they do not depend on internal state names.

Checklist

  • Only independent user choices are stored as state
  • Results and counts are derived during render
  • State lives in the closest common parent
  • Filters are reflected in and restored from the URL
  • Empty results explain the cause and offer a reset
  • Tests interact through the UI like a learner would

Share or cite this guide

Innovate with Ajay Editorial (2026-10-07). React Data Flow in Practice: Build a Filterable Course Catalogue. https://innovatewithajay.com/articles/react-data-flow-filterable-catalogue

Editorial approach, sources and corrections

YOUR NEXT CHAPTER

You have the curiosity.
Let’s turn it into capability.

Start with a practical workshop or bring a specific question to Ajay.

Chat with Ajay