Why I Stripped My UI Library to Build a High-Performance Component
Article Summary
Ashan Perera from PickMe Engineering hit a performance wall that every React developer dreads: typing a single character into a table cell caused a multi-second freeze. His solution? Strip out the entire UI library.
Building an editable table for 1,000+ rows with real-time cross-row validation seemed straightforward using Ant Design and React Hook Form. But at 100 rows per page, the app became unusable. What followed was a deep dive into React's reconciliation bottleneck and a controversial architectural decision.
Key Takeaways
- Ant Design Form caused multi-second lag at 100 rows due to centralized state reconciliation
- Web Workers solved CPU blocking but created async UX friction and validation queues
- Ditching useState for useRefs and removing AntD achieved instant performance on main thread
- Single reducer with imperative DOM updates outperformed both modern React patterns and Web Workers
- Legacy Angular app with direct DOM manipulation exposed React's tree-walking overhead
By replacing declarative React patterns with imperative JavaScript and removing the UI library entirely, the team achieved instant performance for a 1,000+ row editable table with real-time validation.
About This Article
Ashan Perera's team had to validate data across 1,000+ rows of CSV files in real time. The challenge was handling conflicts between values in different rows, like Row 1 and Row 999, and showing errors at the cell level immediately.
Instead of using React's useState and useEffect, the team switched to useRefs with plain JavaScript objects. This let them skip React's state management entirely and use a single Reducer function to handle all validation logic.
The final version used imperative DOM updates and a custom TypeScript table built without Ant Design. It was faster on the main thread than both the Web Worker approach and the legacy Angular application.