Skip to main content

React & IndexedDB: Validating 10k CSV Rows in 20ms

How to validate 10,000 CSV rows client-side in TypeScript in 20.11ms before touching your server, paired with an IndexedDB helper for drafts.

AI-written
Inewgen
08 Nov 2026Source: Dev.to4 min read (0 views)
Share
React & IndexedDB: Validating 10k CSV Rows in 20ms

Stock photo for illustration only, not from the actual event

Font size
  • Validates 10,000 CSV rows containing 40,000 cells directly in the browser in just 20.11ms.
  • Swaps out Array.prototype.some() for a Set to avoid performance bottlenecks from duplicate ID checks.
  • Implements a concise 45-line IndexedDB helper to bypass the 5MB localStorage quota limit.
  • Emphasizes using an RFC-4180 parser to prevent quoted commas from shifting column indices.

Observing a user import a 10,000-row billing CSV over spotty Wi-Fi on a standard web application typically reveals a frustrating experience. They select the file, wait ten seconds for the progress bar to crawl to 100%, and get bounced back by a red toast message showing a 400 Bad Request due to an invalid amount on row 7,500. This forces them to fix row 7,500, re-upload the entire file, and discover yet another typo on row 8,102.

Furthermore, if their connection drops while editing rows in the UI and they refresh the page, the situation usually deteriorates. Many applications attempt to stash draft uploads in localStorage, forgetting that browsers cap localStorage around 5 MB and block the main thread synchronously on writes, which ultimately throws a QuotaExceededError precisely when the user needs a backup most.

These challenges can be resolved entirely on the frontend without importing a bulky 200 KB validation library. In the companion repository (github.com/endlessfountain/react-offline-sheet-guard), a lightweight TypeScript preflight check validates 10,000 CSV rows spanning 40,000 cells in 20.11 ms before a single byte hits the network, paired with a 45-line IndexedDB helper to ensure multi-megabyte drafts survive offline refreshes.

While checking whether an email looks valid or verifying if a seatCount is an integer is relatively cheap, the operation that quietly destroys browser performance on 10,000-row sheets is duplicate ID detection.

code editor programming screen laptop no logo

Stock photo for illustration only, not from the actual event

10,000CSV Rows
20.11msProcessing Time
418.8 KBWasted Upload Saved

When developers write quick client-side validators, they often reach for Array.prototype.some() inside a row loop, which results in around 50 million string comparisons and locks the tab for nearly a second on mid-range laptops. Swapping that array scan for a Set keeps duplicate detection running at O(1) per row, as implemented in src/engine/sheetValidator.ts.

Never miss the latest news?

Subscribe to get news summaries by email - not often enough to be annoying.

โฆษณา

Executing preflight checks on the frontend using TypeScript and IndexedDB significantly improves user experience by reducing server load and network bandwidth waste. However, developers must remember that client-side validation is purely a UX optimization and not a robust security boundary. Malformed payloads can still be sent directly to your API endpoints via tools like curl, meaning exact backend validation rules must remain strictly enforced.

Running npm test in the repository generates a 418.8 KB, 10,000-row CSV file containing four planted errors: a duplicate ID at row 50, a bad email at row 500, a string amount of "$1200" at row 2,500, and 3.5 seats at row 7,500.

"20 milliseconds is barely over a single 60Hz browser frame (16.6ms), and catching those four typos upfront avoids shipping 418.8 KB over the wire on a doomed POST request."

endlessfountain

Twenty milliseconds is barely over a single 60Hz browser frame at 16.6ms, and catching those four typos upfront successfully avoids shipping 418.8 KB over the network on a doomed POST request.

Stashing multi-megabyte drafts in IndexedDB without external packages can be achieved easily. Raw IndexedDB features an antiquated callback API from 2012 that often frightens developers into installing wrappers or falling back to localStorage. In practice, wrapping open, put, and get operations in Promises to save and restore upload drafts by key takes only about 35 lines of code in src/storage/draftDb.ts.

Source: Dev.to

Comments

Leave a Comment
0/2000

Found something wrong in this article? Report an issue with this article