Skip to content

inp.repeated state update

github-actions[bot] edited this page Sep 6, 2026 · 1 revision

inp.repeated-state-update

Rule ID: inp.repeated-state-update Severity: WARN Category: inp Target Standards: React 18+ Automatic Batching Specification, W3C Web Performance Working Group (Interaction to Next Paint - INP), Concurrent React Scheduling & Reconciliation Cost


1. Overview & Core Invariant

Repeated state updater calls inside loops breaking automatic batching trigger cascading re-renders

Core Invariant:

"React state setters must not be repeatedly invoked within loop iterations that break automatic batching (such as asynchronous loops containing 'await' or 'flushSync')."


2. Technical Grounding & Engine Realities

While React 18 automatically batches multiple state updates within standard synchronous handlers, asynchronous loops (e.g. 'for ... of' with 'await' inside) or explicit 'flushSync' blocks break automatic batching.

Calling a state updater on every iteration of an asynchronous loop causes React to trigger a full re-render, VDOM diffing, and reconciliation cycle on every microtask tick.

This creates an enormous render queue backlog on the main thread, stalling user interactions and causing high Interaction to Next Paint (INP) latency.

Accumulating results locally into an array and issuing a single state update after the loop completes ensures a single, batched render pass.


3. Vulnerability & Risk Taxonomy

Risk Vector Severity Impact
Per-Iteration Re-render Cascades HIGH Each iteration of an async loop schedules a separate render pass, saturating the React scheduler and freezing UI input.
Presentation Delay Ballooning MEDIUM Successive re-renders continuously postpone the browser paint phase, severely degrading INP.

4. Non-Compliant Code Patterns (Bad Examples)

TSX (State updater called on each iteration of an async loop):

for (const item of items) {
  const detail = await fetchDetail(item.id);
  setItems(prev => [...prev, detail]); // Memicu re-render pada setiap iterasi!
}

5. Compliant Implementation Patterns (Good Examples)

TSX (Accumulating all results and updating state once after loop completion):

const results = [];
for (const item of items) {
  results.push(await fetchDetail(item.id));
}
setItems(prev => [...prev, ...results]); // Hanya satu siklus render

6. How to Suppress (Ignore Directives)

If this pattern is required for an intentional exception, suppress the diagnostic using the canonical Charites Rule ID:

<!-- charites:ignore inp.repeated-state-update intentional exception -->
// charites:ignore inp.repeated-state-update intentional exception

7. Configuration Reference (charites.yaml)

rules:
  inp.repeated-state-update:
    severity: warn # error | warn | info | off

8. Architectural Domain & Verification Reference


Rule Categories

A11y (16 rules)
Browser (12 rules)
Cls (16 rules)
Design (1 rules)
Ergonomy (5 rules)
Inp (16 rules)
Lcp (16 rules)
Mobile (5 rules)
Performance (16 rules)
Pwa (10 rules)
Responsive (18 rules)
Semantic (1 rules)
Theme (32 rules)
Ux (20 rules)

Clone this wiki locally