What's Actually Happening
React components fail to render when there are errors in JSX syntax, incorrect state updates, missing props, or component lifecycle issues. The component either doesn't appear on screen or shows an error boundary message.
The Error You'll See
Blank screen:
// Nothing renders, page is blank
// No error in consoleError boundary:
Error: Something went wrong.
Error: Minified React error #323Console error:
Warning: Each child in a list should have a unique "key" prop.
Uncaught Error: Component is not defined
TypeError: Cannot read properties of undefinedWhy This Happens
- 1.JSX syntax error - Incorrect HTML structure
- 2.Missing return - Component doesn't return JSX
- 3.Wrong state update - Mutating state directly
- 4.Missing key prop - List items without keys
- 5.Null/undefined props - Accessing properties on null
- 6.Wrong import - Component not imported correctly
Step 1: Check Component Returns JSX
```jsx // WRONG: Component doesn't return anything function MyComponent() { const data = "Hello"; // Missing return! }
// CORRECT: Component returns JSX function MyComponent() { const data = "Hello"; return <div>{data}</div>; }
// WRONG: Not returning in arrow function const MyComponent = () => { <div>Hello</div> // Implicit return needs parentheses }
// CORRECT: Use parentheses for implicit return const MyComponent = () => ( <div>Hello</div> )
// Or explicit return const MyComponent = () => { return <div>Hello</div>; } ```
Step 2: Check JSX Syntax
```jsx // WRONG: Unclosed tag function MyComponent() { return <div><p>Hello</div>; }
// CORRECT: Properly closed tags function MyComponent() { return <div><p>Hello</p></div>; }
// WRONG: Multiple root elements function MyComponent() { return ( <div>First</div> <div>Second</div> // Error: Adjacent JSX elements ); }
// CORRECT: Single root element function MyComponent() { return ( <> <div>First</div> <div>Second</div> </> ); }
// WRONG: Using class instead of className <div class="container"> // React uses className
// CORRECT: <div className="container"> ```
Step 3: Fix State Updates
```jsx // WRONG: Mutating state directly function Counter() { const [count, setCount] = useState(0);
const increment = () => { count = count + 1; // Don't mutate! };
return <button onClick={increment}>{count}</button>; }
// CORRECT: Use setState function function Counter() { const [count, setCount] = useState(0);
const increment = () => { setCount(count + 1); // Correct };
return <button onClick={increment}>{count}</button>; }
// For objects, spread to create new object const [user, setUser] = useState({ name: '', email: '' });
// WRONG: user.name = 'John'; // Mutation
// CORRECT: setUser({ ...user, name: 'John' }); // New object setUser(prev => ({ ...prev, name: 'John' })); // Using callback ```
Step 4: Handle Null and Undefined
```jsx // WRONG: Accessing property on undefined function UserProfile({ user }) { return <div>{user.name}</div>; // Error if user is undefined }
// CORRECT: Add null check function UserProfile({ user }) { if (!user) return <div>Loading...</div>; return <div>{user.name}</div>; }
// Or use optional chaining function UserProfile({ user }) { return <div>{user?.name}</div>; }
// Or provide default value function UserProfile({ user = {} }) { return <div>{user.name}</div>; }
// Or use && for conditional rendering function UserProfile({ user }) { return ( <div> {user && <span>{user.name}</span>} </div> ); } ```
Step 5: Add Unique Keys for Lists
```jsx // WRONG: Missing key prop function UserList({ users }) { return ( <ul> {users.map(user => ( <li>{user.name}</li> // Warning: Missing key ))} </ul> ); }
// CORRECT: Add unique key function UserList({ users }) { return ( <ul> {users.map(user => ( <li key={user.id}>{user.name}</li> ))} </ul> ); }
// WRONG: Using index as key (anti-pattern) {items.map((item, index) => ( <li key={index}>{item.name}</li> // Use only if no stable ID ))}
// CORRECT: Use stable unique ID {items.map(item => ( <li key={item.id}>{item.name}</li> ))}
// For nested lists, use combination
{categories.map(category => (
<div key={category.id}>
{category.items.map(item => (
<span key={${category.id}-${item.id}}>{item.name}</span>
))}
</div>
))}
```
Step 6: Fix Component Imports
```jsx // WRONG: Wrong import path import MyComponent from './MyComponent'; // File is MyComponent.jsx?
// Check file extension and path // MyComponent.jsx, MyComponent.js, index.jsx in MyComponent/
// WRONG: Default import for named export // In component file: export const MyComponent = () => <div>Hello</div>;
// Import: import MyComponent from './MyComponent'; // Wrong!
// CORRECT: Named import for named export import { MyComponent } from './MyComponent';
// Or change to default export: export default function MyComponent() { return <div>Hello</div>; }
// Then use default import: import MyComponent from './MyComponent'; ```
Step 7: Check useEffect Dependencies
```jsx // WRONG: Infinite render loop function DataFetcher() { const [data, setData] = useState([]);
useEffect(() => { fetchData().then(setData); }); // Missing dependency array = runs every render
return <div>{data.length}</div>; }
// CORRECT: Add empty dependency for mount only useEffect(() => { fetchData().then(setData); }, []); // Run once on mount
// WRONG: Stale closure function Counter() { const [count, setCount] = useState(0);
useEffect(() => { const interval = setInterval(() => { console.log(count); // Always logs 0 }, 1000); return () => clearInterval(interval); }, []); // count not in dependencies }
// CORRECT: Include dependencies useEffect(() => { const interval = setInterval(() => { console.log(count); }, 1000); return () => clearInterval(interval); }, [count]); // count in dependencies ```
Step 8: Debug with React DevTools
```jsx // Install React Developer Tools browser extension
// Check component tree // 1. Open DevTools (F12) // 2. Go to React tab (Components) // 3. Select component to inspect props and state
// Common debugging patterns: function MyComponent({ data }) { console.log('MyComponent rendered', data);
// Log state changes useEffect(() => { console.log('Data changed:', data); }, [data]);
// Use debugger if (!data) { debugger; // Pauses execution }
return <div>{data}</div>; }
// React.StrictMode causes double render in dev // This is intentional for finding issues <React.StrictMode> <App /> </React.StrictMode> ```
Step 9: Check Conditional Rendering
```jsx // WRONG: Falsy value renders 0 function Cart({ items }) { return ( <div> {items.length && <CartList items={items} />} </div> ); } // If items.length is 0, renders "0" on screen
// CORRECT: Use explicit boolean function Cart({ items }) { return ( <div> {items.length > 0 && <CartList items={items} />} </div> ); }
// Or ternary for fallback function Cart({ items }) { return ( <div> {items.length > 0 ? ( <CartList items={items} /> ) : ( <p>Cart is empty</p> )} </div> ); }
// Or use double negation {!!items.length && <CartList items={items} />} ```
Step 10: Check Context and Provider
```jsx // WRONG: Using context without provider const ThemeContext = createContext('light');
function App() { return <Button />; // No ThemeProvider }
function Button() { const theme = useContext(ThemeContext); return <button className={theme}>Click</button>; }
// CORRECT: Wrap with provider function App() { return ( <ThemeContext.Provider value="dark"> <Button /> </ThemeContext.Provider> ); }
// Check provider value function App() { const [theme, setTheme] = useState('light');
return ( <ThemeContext.Provider value={{ theme, setTheme }}> <Button /> </ThemeContext.Provider> ); }
// Consumer side: function Button() { const { theme } = useContext(ThemeContext); return <button className={theme}>Click</button>; } ```
React Rendering Issues Checklist
| Issue | Symptom | Fix |
|---|---|---|
| No return | Blank | Add return statement |
| State mutation | No update | Use setState |
| Missing key | Warning | Add unique key |
| Null prop | Error | Add null check |
| Wrong import | Undefined | Check import path |
| Missing deps | Stale data | Add to useEffect |
Verify the Fix
```jsx // After fixing component issues
// 1. Check console for errors // Should be no red errors
// 2. Use React DevTools // Component should appear in tree
// 3. Check props and state in DevTools // Values should be as expected
// 4. Test user interactions // State updates should reflect in UI
// 5. Verify all conditions // Edge cases should handle gracefully
// 6. Check performance // No unnecessary re-renders ```
Related Issues
- [Fix React useState Not Updating](/articles/fix-react-usestate-not-updating)
- [Fix React useEffect Infinite Loop](/articles/fix-react-useeffect-infinite-loop)
- [Fix React Props Undefined](/articles/fix-react-props-undefined)