react

Axios API client with interceptors

A centralized API client provides a single place to configure authentication, error handling, and request/response transformations. I use axios for its interceptor support and automatic JSON transformation. Request interceptors attach the JWT token fr

Zustand for lightweight state management

Zustand provides a minimalist alternative to Redux with less boilerplate and better TypeScript support. I create stores with create that hold state and actions. Unlike Context, Zustand doesn't cause unnecessary re-renders—components only update when t

React Error Boundary + error reporting hook

Frontend errors are inevitable, so I’d rather control the blast radius. I wrap unstable sections with an ErrorBoundary that shows a friendly fallback and captures context for reporting. I also avoid spamming the error tracker by including a fingerprin

React Router with protected routes

React Router v6 provides declarative routing with data loading and authentication guards. I wrap protected routes in a ProtectedRoute component that checks authentication state from context and redirects to login if needed. The Navigate component hand

React component composition over inheritance

React favors composition over inheritance for code reuse. Instead of extending component classes, I compose smaller components into larger ones. Higher-order components (HOCs) wrap components to add behavior, while render props pass rendering logic as

Frontend: skeleton loading instead of spinners

Spinners hide layout shifts and make an app feel slow even when it isn’t. Skeletons preserve layout and give users a sense of progress without jumping content around. I keep skeleton components simple and match the shape of the final UI. One practical

Debounced search input (React)

Search boxes are a classic place to accidentally fire a request on every keystroke. I debounce the value that triggers the query (not the input rendering) so typing stays responsive, and I cancel/ignore stale requests so results don’t arrive out of or

Form handling with React Hook Form

React Hook Form provides performant form handling with minimal re-renders. Unlike controlled components that re-render on every keystroke, it uses uncontrolled inputs with refs. The register function connects inputs to the form state, and handleSubmit

Infinite scroll with Intersection Observer

Infinite scroll loads more content as users reach the bottom of a list, improving perceived performance over pagination. I use the Intersection Observer API to detect when a sentinel element becomes visible, then trigger the next page fetch. React Que

Keyboard navigation and focus management

Accessible apps support keyboard-only navigation with proper focus management. Tab order should follow visual order, and all interactive elements must be keyboard accessible. I use tabIndex={0} to make custom controls focusable and tabIndex={-1} for p

Markdown rendering with react-markdown

Rich text content from Rails often comes as Markdown. The react-markdown library renders Markdown to React components with customizable styling and sanitization. I configure it to use syntax highlighting via react-syntax-highlighter for code blocks, c

React app structure with Vite and TypeScript

Vite provides lightning-fast dev server startup and hot module replacement compared to Create React App. I scaffold React projects with TypeScript for type safety across the entire frontend. The folder structure separates concerns: components for reus