Use Lazy State Initialization
Install this skill
npx skills add vercel-labs/agent-skillsWorks across Claude Code, Cursor, Codex, Copilot & Antigravity
Lazy state initialization in React prevents expensive computations from executing on every component render. By passing a function rather than a direct value to the useState hook, React invokes that function only during the initial mounting phase. This optimization is critical when the initial state depends on synchronous blocking operations, such as parsing complex JSON objects from localStorage, constructing large search indexes from props, or calculating expensive data structures. Without this pattern, the application performs redundant work during every update cycle triggered by props or state changes, which can lead to noticeable latency or frame drops in performance-sensitive applications. Implementing this function wrapper ensures that heavy logic stays scoped to the birth of the component, preserving system resources while maintaining clean, predictable state management across the lifecycle of your UI components.
When to Use This Skill
- •Parsing local storage strings on app startup
- •Generating large filter or search indexes from incoming props
- •Initializing complex class instances or data mapping tables
- •Reading computed values from the DOM during component mount
How to Invoke This Skill
Example prompts that trigger this skill in Claude Code, Cursor, or Antigravity:
- “how to optimize expensive useState initializers
- “stop useState from running on every render
- “perform expensive calculation only once during state setup
- “lazy initialization of state in React
- “fix performance lag when initializing state from localStorage
What this skill does
- •Defers execution of initializer logic until the first mount
- •Eliminates repeated execution of heavy functions on subsequent renders
- •Optimizes performance for browser storage data retrieval
- •Reduces CPU overhead for data structure creation
- •Ensures consistent state initialization without side effects
When not to use it
- ✕Initializing simple primitive values like strings, numbers, or booleans
- ✕Referencing existing props directly when no computation is involved
- ✕Creating empty object or array literals
Example workflow
- Identify a useState hook that consumes a high-latency calculation
- Wrap the calculation logic inside an arrow function
- Pass this anonymous function as an argument to the useState hook
- Verify that the computation logic logs to the console only once
- Confirm the UI renders correctly on subsequent state updates
Prerequisites
- –Basic knowledge of React hooks
- –Understanding of the component render cycle
Pitfalls & limitations
- !Over-optimizing trivial operations that perform worse due to function closure overhead
- !Accidentally referencing variables inside the function that change but should remain constant
- !Adding unnecessary complexity to codebases where performance bottlenecks do not exist
FAQ
How it compares
Unlike manual initialization or simple assignments, lazy initialization provides a native React mechanism to gate-keep execution, ensuring the logic is strictly scoped to the component's mounting phase.
📄 Full skill instructions — original source: vercel-labs/agent-skills
Pass a function to
useState for expensive initial values. Without the function form, the initializer runs on every render even though the value is only used once.**Incorrect (runs on every render):**
function FilteredList({ items }: { items: Item[] }) {
// buildSearchIndex() runs on EVERY render, even after initialization
const [searchIndex, setSearchIndex] = useState(buildSearchIndex(items))
const [query, setQuery] = useState('')
// When query changes, buildSearchIndex runs again unnecessarily
return <SearchResults index={searchIndex} query={query} />
}
function UserProfile() {
// JSON.parse runs on every render
const [settings, setSettings] = useState(
JSON.parse(localStorage.getItem('settings') || '{}')
)
return <SettingsForm settings={settings} onChange={setSettings} />
}**Correct (runs only once):**
function FilteredList({ items }: { items: Item[] }) {
// buildSearchIndex() runs ONLY on initial render
const [searchIndex, setSearchIndex] = useState(() => buildSearchIndex(items))
const [query, setQuery] = useState('')
return <SearchResults index={searchIndex} query={query} />
}
function UserProfile() {
// JSON.parse runs only on initial render
const [settings, setSettings] = useState(() => {
const stored = localStorage.getItem('settings')
return stored ? JSON.parse(stored) : {}
})
return <SettingsForm settings={settings} onChange={setSettings} />
}Use lazy initialization when computing initial values from localStorage/sessionStorage, building data structures (indexes, maps), reading from the DOM, or performing heavy transformations.
For simple primitives (
useState(0)), direct references (useState(props.value)), or cheap literals (useState({})), the function form is unnecessary.How to Use This Skill Unit
Option A: Project-Specific (Recommended)
- Click "Download" above
- In your project, create the directory:
.agent/skills/rerender-lazy-state-init/ - Save the file as
SKILL.md - The agent will automatically discover the skill based on its description.
Option B: Global Installation (All Agents)
Save the file to these locations to make it available across all projects:
- Claude Code:
~/.claude/skills/vercel-labs/agent-skills/rerender-lazy-state-init/SKILL.md - Cursor:
~/.cursor/skills/vercel-labs/agent-skills/rerender-lazy-state-init/SKILL.md - Antigravity:
~/.gemini/antigravity/skills/vercel-labs/agent-skills/rerender-lazy-state-init/SKILL.md
🚀 Install with CLI:npx skills add vercel-labs/agent-skills