How to Fix INP in React Apps (Interaction to Next Paint, 2027)

Suman SharmaSuman Sharma

Interaction to Next Paint (INP) replaced First Input Delay as a Core Web Vital in March 2024. It measures how long the page takes to visually respond to clicks, taps, and key presses across the whole visit. React apps often struggle with it because big re-renders block the main thread.

The thresholds

INPRating
≤ 200 msGood
200–500 msNeeds improvement
> 500 msPoor

Measured at the 75th percentile of real user visits.

Step 1: Find the slow interaction

  • Field data: Search Console's Core Web Vitals report, or the web-vitals library with attribution, which tells you which element and interaction was slow.
  • Lab: Chrome DevTools Performance panel. Record, interact, and look for long tasks.
import { onINP } from "web-vitals/attribution"; onINP((metric) => { console.log(metric.value, metric.attribution.interactionTarget); });

Step 2: Understand the three parts

INP = input delay + processing time + presentation delay.

  • Input delay: main thread busy when the user clicks (hydration, third-party scripts).
  • Processing: your event handler and React's render.
  • Presentation: layout and paint of the result.

Step 3: Fix

Render less

  • Move state down to the component that needs it.
  • Split big components so a keystroke doesn't re-render the whole page.
  • Memoise expensive children (React.memo, useMemo) where profiling shows it helps.

Mark non-urgent updates as transitions

const [query, setQuery] = useState(""); const [isPending, startTransition] = useTransition(); function onChange(e: React.ChangeEvent<HTMLInputElement>) { setQuery(e.target.value); // urgent: update the input startTransition(() => { setFilter(e.target.value); // non-urgent: filter a big list }); }

Virtualise long lists

Rendering 5,000 rows on every filter change kills INP. Use a virtualised list.

Yield in long handlers

Break heavy work into chunks so the browser can paint in between, using scheduler.yield() where supported or a setTimeout fallback.

Ship less JavaScript

  • Use Server Components so less code hydrates (App Router lessons).
  • Lazy-load heavy widgets (maps, editors).
  • Audit third-party scripts. They're often the biggest input-delay source.

Frequently asked questions

What is a good INP score?

Google considers an INP of 200 milliseconds or less 'good', 200–500 ms 'needs improvement', and over 500 ms 'poor', measured at the 75th percentile of page loads.

What causes poor INP in React?

Long tasks on the main thread during interactions: large re-renders, expensive event handlers, heavy third-party scripts, and hydration work competing with user input.

Does useTransition improve INP?

It can. Marking non-urgent updates as transitions lets React keep the UI responsive to the input while rendering the expensive part later.

Contact

Get in Touch

Want to call me? book a call and I'll respond in the available time slot. I will ignore all soliciting.