React makes building user interfaces easier, but certain errors appear repeatedly, especially when working with components, state, props, effects, and lists. Understanding these errors can save hours of debugging.
1. “Objects are not valid as a React child”
This happens when you try to render a JavaScript object directly.
const user = {
name: "John",
age: 25
};
return <h1>{user}</h1>;
React cannot render the object itself.
Fix:
return <h1>{user.name}</h1>;
Or, for debugging:
<pre>{JSON.stringify(user, null, 2)}</pre>
2. Missing key Prop in Lists
When rendering arrays, React expects each element to have a unique key.
const users = ["John", "Jane", "Mike"];
return (
<ul>
{users.map(user => (
<li>{user}</li>
))}
</ul>
);
You may see:
Each child in a list should have a unique "key" prop.
Fix:
{users.map(user => (
<li key={user}>{user}</li>
))}
Keys help React identify which items have changed, been added, or removed.
Avoid using array indexes as keys when the list can be reordered or modified.
3. “Cannot read properties of undefined”
A component may try to access a property before the data exists.
<h1>{user.name}</h1>
If user is initially undefined, this can cause an error.
Fix with optional chaining:
<h1>{user?.name}</h1>
Or conditionally render the component:
{user && <h1>{user.name}</h1>}
4. Updating State Incorrectly
State updates should use the state setter rather than directly modifying the state variable.
Incorrect:
count = count + 1;
Correct:
setCount(count + 1);
For updates based on the previous state, use the functional form:
setCount(prevCount => prevCount + 1);
This is particularly important when multiple state updates may be batched.
5. Infinite useEffect Loops
An incorrectly configured effect can run continuously.
useEffect(() => {
setCount(count + 1);
}, [count]);
The effect changes count, which causes the effect to run again, creating a loop.
The solution depends on the intended behavior. If the effect should run only once when the component mounts:
useEffect(() => {
// logic
}, []);
Do not simply remove dependencies to silence a warning. The dependency array should represent the values the effect actually uses.
6. Calling Hooks Conditionally
Hooks must be called in the same order on every render.
Incorrect:
if (isLoggedIn) {
useEffect(() => {
// ...
}, []);
}
Correct:
useEffect(() => {
if (isLoggedIn) {
// ...
}
}, [isLoggedIn]);
The same rule applies to useState, useMemo, useCallback, and other Hooks.
7. Forgetting to Return JSX
A component must return the UI it is supposed to render.
Incorrect:
function Welcome() {
<h1>Hello</h1>;
}
Correct:
function Welcome() {
return <h1>Hello</h1>;
}
For arrow functions, be careful with curly braces:
const Welcome = () => (
<h1>Hello</h1>
);
8. Incorrect Event Handler
This mistake calls the function immediately instead of passing it as an event handler.
Incorrect:
<button onClick={handleClick()}>
Click
</button>
Correct:
<button onClick={handleClick}>
Click
</button>
If arguments are required:
<button onClick={() => handleClick(id)}>
Click
</button>
9. Using class Instead of className
JSX uses className for CSS classes.
Incorrect:
<div class="container">
Hello
</div>
Correct:
<div className="container">
Hello
</div>
This is because class is a JavaScript keyword-related attribute conflict in JSX’s DOM property model.
10. Component Name Starts With a Lowercase Letter
React treats lowercase JSX tags as HTML elements.
function profile() {
return <h1>Profile</h1>;
}
<profile />
React interprets <profile /> as a custom HTML-like element rather than your React component.
Use PascalCase:
function Profile() {
return <h1>Profile</h1>;
}
<Profile />
11. State Updates Don’t Happen Immediately
This can be confusing:
setCount(count + 1);
console.log(count);
The console.log may still show the previous value because React schedules state updates rather than changing the variable immediately.
If you need to perform something when the value changes:
useEffect(() => {
console.log(count);
}, [count]);
12. Props Are Read-Only
You should not directly modify props inside a component.
Incorrect:
function User({ name }) {
name = "Mike";
return <h1>{name}</h1>;
}
Instead, use state if the component needs to manage a changing value:
function User({ name }) {
const [currentName, setCurrentName] = useState(name);
return <h1>{currentName}</h1>;
}
13. Import/Export Errors
A common error occurs when a default export is imported as a named export, or vice versa.
Default export:
export default Button;
Import:
import Button from "./Button";
Named export:
export { Button };
Import:
import { Button } from "./Button";
The export and import syntax must match.
14. “Too Many Re-renders”
This usually happens when something triggers a state update during rendering.
Incorrect:
function Counter() {
const [count, setCount] = useState(0);
setCount(count + 1);
return <h1>{count}</h1>;
}
Every render updates the state, which causes another render.
Move the update into an event handler or an appropriately configured effect:
<button onClick={() => setCount(count + 1)}>
Increment
</button>
15. Rendering Before Data Is Available
Data from an API is often unavailable during the first render.
Instead of assuming it exists:
return <h1>{data.user.name}</h1>;
Handle loading and missing data:
if (loading) {
return <p>Loading...</p>;
}
if (!data) {
return <p>No data found.</p>;
}
return <h1>{data.user.name}</h1>;
This makes components much more resilient.
Quick Debugging Checklist
When a React application throws an error, check:
- Console: Read the complete error message and stack trace.
- Props: Is the expected data actually being passed?
- State: Could the value initially be
undefinedornull? - Lists: Does every rendered list item have a stable
key? - Hooks: Are Hooks being called at the top level?
- Effects: Are dependencies correct?
- Events: Are handlers being passed rather than immediately executed?
- Imports: Do your named/default exports match?
- Rendering: Are you accidentally trying to render an object?
- State updates: Are you modifying state through its setter?
Most React errors become much easier to solve once you identify what React expected, what it actually received, and which component introduced the mismatch.

Latest tech news and coding tips.