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.
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> key Prop in ListsWhen 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.
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>} 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.
useEffect LoopsAn 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.
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.
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>
); 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> class Instead of classNameJSX 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.
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 /> 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]); 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>;
} 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.
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> 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.
When a React application throws an error, check:
undefined or null?key?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.
The C programming language is a foundational, general-purpose computer programming language created by Dennis Ritchie at Bell Labs in 1972. Originally developed to…
What Is Homebrew? Homebrew is a package manager for macOS and Linux that makes it easy to…
JavaScript gives you several ways to iterate over an array. Some are better for simple…
A web server is the software responsible for receiving requests from clients, processing those requests,…
A shell prompt is the text displayed by a command-line shell to show that it is ready…
A SOC Analyst (Security Operations Center Analyst) is one of the frontline defenders of an organization’s cybersecurity…