[ PROMPT_NODE_24707 ]
React
[ SKILL_DOCUMENTATION ]
# React Error Patterns
Common React/Next.js errors with diagnosis and solutions.
## Hydration Errors
### Hydration Mismatch
```
Hydration failed because the initial UI does not match what was rendered on the server.
```
**Causes**:
1. Server and client render different content
2. Using browser-only APIs during render
3. Date/time formatting differences
4. Random values in render
**Common Culprits**:
```jsx
// These cause hydration mismatch
{new Date().toLocaleString()} // Time differs
{Math.random()} // Random differs
{typeof window !== 'undefined'} // Condition differs
{localStorage.getItem('key')} // No localStorage on server
```
**Solutions**:
```jsx
// Use useEffect for client-only code
const [mounted, setMounted] = useState(false)
useEffect(() => {
setMounted(true)
}, [])
if (!mounted) return null // Or return skeleton
return
{localStorage.getItem('theme')}
```
```jsx
// Suppress hydration warning (last resort)
```
```jsx
// Use 'use client' directive in Next.js App Router
'use client'
export default function ClientComponent() {
// Client-only code here
}
```
---
### Text content does not match server-rendered HTML
```
Text content does not match server-rendered HTML.
```
**Same as hydration mismatch** - content differs between server and client.
**Quick Check**:
1. Are you using `Date`, `Math.random()`?
2. Are you accessing `window`, `document`, `localStorage`?
3. Are you using browser-specific formatting?
---
## Hooks Errors
### Invalid hook call
```
Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
```
**Causes**:
1. Hook called outside component
2. Hook called in class component
3. Hook called in regular function
4. Multiple React versions
5. Breaking rules of hooks
**Diagnosis**:
```bash
# Check for multiple React versions
npm ls react
npm ls react-dom
```
**Solutions**:
```jsx
// Wrong - hook in regular function
function getData() {
const [data, setData] = useState(null) // Error!
}
// Correct - hook in component
function MyComponent() {
const [data, setData] = useState(null) // OK
}
// Correct - custom hook
function useData() {
const [data, setData] = useState(null)
return data
}
```
```bash
# Fix multiple React versions
npm dedupe
# Or check and align versions in package.json
```
---
### Rendered more hooks than during previous render
```
Rendered more hooks than during the previous render.
```
**Causes**:
1. Conditional hook calls
2. Hook inside loop
3. Early return before all hooks
**Solutions**:
```jsx
// Wrong - conditional hook
function MyComponent({ condition }) {
if (condition) {
const [state, setState] = useState() // Error!
}
}
// Correct - always call hooks
function MyComponent({ condition }) {
const [state, setState] = useState()
if (!condition) {
return null
}
return {state}
}
```
```jsx
// Wrong - hook in loop
items.forEach(item => {
const [value, setValue] = useState() // Error!
})
// Correct - use single state for all items
const [values, setValues] = useState({})
```
---
### Cannot update state on unmounted component
```
Warning: Can't perform a React state update on an unmounted component.
```
**Causes**:
1. Async operation completes after unmount
2. Missing cleanup in useEffect
3. Event listener not removed
**Solutions**:
```jsx
// Use cleanup with flag
useEffect(() => {
let mounted = true
fetchData().then(data => {
if (mounted) {
setData(data)
}
})
return () => {
mounted = false
}
}, [])
```
```jsx
// With AbortController
useEffect(() => {
const controller = new AbortController()
fetch(url, { signal: controller.signal })
.then(res => res.json())
.then(setData)
.catch(err => {
if (err.name !== 'AbortError') {
setError(err)
}
})
return () => controller.abort()
}, [url])
```
---
## Key Errors
### Each child in a list should have a unique "key" prop
```
Warning: Each child in a list should have a unique "key" prop.
```
**Causes**:
1. Missing key prop in map()
2. Using index as key (not always wrong but can cause issues)
3. Duplicate keys
**Solutions**:
```jsx
// Wrong - no key
{items.map(item => )}
// Wrong - index as key (problematic if list reorders)
{items.map((item, index) => )}
// Correct - unique identifier
{items.map(item => )}
// If no ID, create stable key
{items.map(item => )}
```
**When index is OK**:
- List is static (never reorders)
- Items have no unique ID
- List never re-renders
---
### Encountered two children with the same key
```
Warning: Encountered two children with the same key "123".
```
**Causes**:
1. Duplicate IDs in data
2. Wrong key property used
3. Key generation produces duplicates
**Solutions**:
```jsx
// Debug - find duplicates
const keys = items.map(i => i.id)
const duplicates = keys.filter((k, i) => keys.indexOf(k) !== i)
console.log('Duplicates:', duplicates)
// Fix - combine fields for uniqueness
{items.map((item, index) => (
))}
```
---
## Props Errors
### Cannot read properties of undefined (reading 'map')
```
TypeError: Cannot read properties of undefined (reading 'map')
```
**Causes**:
1. Data not loaded yet
2. API returned undefined
3. Wrong prop passed
**Solutions**:
```jsx
// Guard with optional chaining
{items?.map(item => )}
// With default value
{(items || []).map(item => )}
// Loading state
if (!items) return
return items.map(item => )
```
---
### Objects are not valid as a React child
```
Objects are not valid as a React child (found: object with keys {x, y}).
```
**Causes**:
1. Rendering object directly instead of its properties
2. Rendering Date object
3. Rendering JSON object
**Solutions**:
```jsx
// Wrong
{user}
// user is object
{new Date()}
// Date is object
// Correct
{user.name}
{new Date().toLocaleDateString()}
{JSON.stringify(data)}
// For debugging
```
---
## useEffect Errors
### Maximum update depth exceeded
```
Maximum update depth exceeded. This can happen when a component calls setState inside useEffect.
```
**Causes**:
1. Missing or wrong dependency array
2. State update triggers re-render that triggers effect
3. Object/array in dependency array creates infinite loop
**Solutions**:
```jsx
// Wrong - missing dependency array
useEffect(() => {
setState(value) // Runs every render = infinite loop
})
// Wrong - object in deps always "changes"
useEffect(() => {
// ...
}, [{ id: 1 }]) // New object every render!
// Correct - stable dependency
useEffect(() => {
setState(value)
}, []) // Empty = only on mount
// Correct - primitive dependency
const { id } = props
useEffect(() => {
// ...
}, [id]) // Primitive, stable comparison
```
```jsx
// For objects, use specific properties directly
const { id, name } = config
useEffect(() => {
// use id, name
}, [id, name])
// Or stringify (use sparingly, can be expensive)
const configStr = JSON.stringify(config)
useEffect(() => {
// ...
}, [configStr])
```
---
### Missing dependency warning
```
React Hook useEffect has a missing dependency: 'value'.
```
**Solutions**:
```jsx
// Option 1: Add the dependency
useEffect(() => {
doSomething(value)
}, [value])
// Option 2: Move value inside effect
useEffect(() => {
const value = calculateValue()
doSomething(value)
}, [])
// Option 3: Use functional update (for setState)
useEffect(() => {
setCount(prev => prev + 1) // No dependency on count
}, [])
// Option 4: Intentionally exclude (with comment)
useEffect(() => {
// Only run on mount, intentionally ignoring value changes
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
```
---
## Next.js Specific Errors
### Error: Invariant: headers() expects to have requestAsyncStorage
```
Error: Invariant: headers() expects to have requestAsyncStorage
```
**Causes**:
1. Using server-only function in client component
2. headers(), cookies() called outside request context
**Solutions**:
```jsx
// Mark as server component (default in app directory)
// Remove 'use client' if present
// Or fetch data in server component, pass to client
// Server Component
async function Page() {
const data = await getData()
return
}
```
---
### Error: Cannot access 'X' before initialization
```
Error: Cannot access 'Component' before initialization
```
**Causes**:
1. Circular imports
2. Component used before defined
3. Import order issues
**Diagnosis**:
```bash
# Check import chain
grep -r "import.*Component" src/
```
**Solutions**:
```jsx
// Lazy load to break circular dependency
const Component = dynamic(() => import('./Component'), { ssr: false })
// Or restructure imports
// Move shared code to separate file
```
---
### Module not found: Can't resolve 'X'
```
Module not found: Can't resolve 'fs'
```
**Causes**:
1. Node.js module used in client code
2. Missing package
3. Wrong import path
**Solutions**:
```jsx
// For Node.js modules in Next.js
// next.config.js
module.exports = {
webpack: (config, { isServer }) => {
if (!isServer) {
config.resolve.fallback = {
fs: false,
path: false,
}
}
return config
}
}
```
```jsx
// Use dynamic import with ssr: false
const Component = dynamic(() => import('./ServerComponent'), { ssr: false })
// Or check environment
if (typeof window === 'undefined') {
// Server-only code
}
```
---
## Build Errors
### Failed to compile
```
Failed to compile
./src/Component.jsx
Module parse failed: Unexpected token
```
**Common Causes**:
1. Syntax error in code
2. Missing babel/typescript config
3. Unsupported syntax
**Check**:
1. Look at the line number mentioned
2. Check for unclosed brackets/quotes
3. Verify file extension matches content
---
### Build error occurred - Cannot read property 'X' of undefined
```
Build error occurred
TypeError: Cannot read property 'map' of undefined
```
**Causes**:
1. Missing data during static generation
2. API call failed during build
3. Environment variable not set
**Solutions**:
```jsx
// Add fallback for missing data
export async function getStaticProps() {
try {
const data = await fetchData()
return { props: { data: data || [] } }
} catch (error) {
return { props: { data: [] } }
}
}
```
---
## Quick Reference Table
| Error | Category | Quick Fix |
|-------|----------|-----------|
| Hydration mismatch | SSR | Use `useEffect` for client-only code |
| Invalid hook call | Hooks | Check hook is in component body |
| More hooks than previous render | Hooks | Don't use conditional hooks |
| Unmounted component update | Async | Add cleanup/mounted flag |
| Missing key prop | List | Add unique `key` to map items |
| Objects not valid as child | Render | Render `obj.property` not `obj` |
| Maximum update depth | useEffect | Check dependency array |
| Cannot access before init | Import | Check for circular imports |
| Module not found: fs | Build | Add webpack fallback |
Source: claude-code-templates (MIT). See About Us for full credits.