DEV Community

Cover image for 15 Common React.js Errors and How to Solve Them
Shubham Joshi
Shubham Joshi

Posted on

15 Common React.js Errors and How to Solve Them

React is a powerful library, but its unique rules (especially around JSX and Hooks) can trip up even experienced developers. Understanding the common pitfalls is the fastest way to master the framework.

Here is an expanded guide covering 15 of the most frequent errors you'll encounter in a React application, complete with the cause and, most importantly, the exact solution.

1. Invalid DOM Property (class vs className)

The Problem

You write standard HTML attribute names like class or for, but React throws a warning in the console:

Warning: Invalid DOM property class. Did you mean className?

The Cause

React uses JSX, which is a syntax extension for JavaScript. Since class is a reserved keyword in JavaScript (used for defining classes), React can't use it directly for HTML attributes. The same applies to for, which must be written as htmlFor when associated with a <label>.

The Solution

Always use className instead of class for defining CSS classes on DOM elements within JSX. Use htmlFor instead of for for label association.

❌ Bad Code ✅ Good Code
jsx<div class="header">Hello</div> jsx<div className="header">Hello</div>

2. Cannot Read Property of Undefined

The Problem

You try to access a property or method (like map()) on an object or array, but the application crashes with an error message:

TypeError: Cannot read property 'map' of undefined (or null)

The Cause

This error usually occurs when you are fetching data asynchronously (e.g., from an API) and your component tries to render the data before it has arrived. The state variable holding the data is often initialized to null or undefined.

The Solution

Use conditional rendering or optional chaining (?.) to ensure you only access properties on an object/array once it has been populated.

❌ Bad Code ✅ Good Code
jsxconst MyList = ({ items }) => { return ( <ul> {items.map(item => <li key={item.id}>{item.name}</li>)} </ul> );}; // If items is undefined, this crashes jsxconst MyList = ({ items }) => { // Use optional chaining or check for existence first: return ( <ul> {items?.map(item => <li key={item.id}>{item.name}</li>)} </ul> );};

3. Component is Not a Function

The Problem

When you try to render a component, the console throws a TypeError indicating the component is not a function:

TypeError: Cannot read properties of undefined (reading 'call')

The Cause

The component was either not imported correctly or was defined using a lowercase name. In React, components must be named starting with an uppercase letter. React treats lowercase tags (like <mycomponent>) as standard HTML elements (<div>, <span>).

The Solution

Ensure your component name starts with a capital letter and that your import statements and file paths are correct.

❌ Bad Code ✅ Good Code
jsx// mycomponent.jsfunction mycomponent() { /* ... */ } // In App.js:<mycomponent /> // React looks for an HTML element jsx// MyComponent.jsfunction MyComponent() { /* ... */ } // In App.js:<MyComponent /> // React looks for a component

4. Objects Are Not Valid as a React Child

The Problem

You try to display a JavaScript object directly within JSX, and React throws a runtime error:

Error: Objects are not valid as a React child (found: object with keys {...}). If you meant to render a collection of children, use an array instead.

The Cause

JSX expressions can only render primitive values like strings, numbers, arrays, or React elements. They cannot render plain JavaScript objects because React doesn't know how to translate an object into a displayable DOM element.

The Solution

If you need to display an object for debugging, convert it to a string using JSON.stringify(). If you need to display its properties, access them directly (e.g., user.name).

❌ Bad Code ✅ Good Code
jsxconst user = { name: "Alice" };<div>{user}</div> jsxconst user = { name: "Alice" };<div> {/* For debugging */} {JSON.stringify(user)} {/* To display a property */} <h1>Hello, {user.name}</h1></div>

5. Maximum Update Depth Exceeded (Infinite Loop)

The Problem

Your component keeps re-rendering itself endlessly, crashing the application with a stack overflow error:

Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate.

The Cause

This is most often caused by calling a state setter function (setState or useState setter) directly within the main body of a functional component or inside a useEffect hook without a proper dependency array.

The Solution

Only call state setters within event handlers, promise callbacks, or inside a useEffect hook with a controlled dependency array (or an empty array [] for mounting effects).

❌ Bad Code ✅ Good Code
jsxfunction Counter() { const [count, setCount] = useState(0); // ❌ Runs on every render, causing an infinite loop. setCount(count + 1); return <h1>{count}</h1>;} jsxfunction Counter() { const [count, setCount] = useState(0); // State update is now triggered by a user event. const handleClick = () => { setCount(prevCount => prevCount + 1); }; return ( <button onClick={handleClick}> Count: {count} </button> );}

6. Expected a String But Got: undefined

The Problem

You pass a prop to a child component, but the prop's value is missing or undefined, leading to a type warning:

Warning: Failed prop type: Invalid prop text of type undefined supplied to MyComponent, expected string.

The Cause

A prop that is expected to be a string or other displayable type is being passed as undefined (often because a parent state or prop value is undefined). React sees undefined and assumes you made a mistake, as it generally expects a displayable value.

The Solution

Always provide a fallback value for props that might be missing, or use conditional rendering to prevent the component from being rendered if essential data is absent.

❌ Bad Code ✅ Good Code
jsx// Assuming user.name is sometimes undefined<Greeting name={user.name} /> `jsx// Use OR (

7. React Hook "useEffect" is Called Conditionally

The Problem

Your code violates the fundamental Rules of Hooks, resulting in a critical error:

Error: React Hook "useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render.

The Cause

You called a React Hook ({% raw %}useState, useEffect, etc.) inside a JavaScript control flow statement like an if statement, a for loop, or a nested function. React relies on a consistent, ordered list of Hook calls across every render.

The Solution

Hooks must always be called unconditionally at the top level of your functional component or custom hook. If you need conditional logic, put the condition inside the Hook's body.

❌ Bad Code ✅ Good Code
jsxfunction MyComponent({ userId }) { if (userId) { // ❌ Error: Hook called conditionally useEffect(() => { fetchData(userId); }, [userId]); } // ...} jsxfunction MyComponent({ userId }) { useEffect(() => { // ✅ Condition is inside the hook's body if (userId) { fetchData(userId); } }, [userId]); // ...}

8. Component's Children Not Recognized (Missing key)

The Problem

When rendering a list of elements using the map() method, the console displays a warning:

Warning: Each child in a list should have a unique "key" prop.

The Cause

When React renders a list, it needs a stable identifier (key) for each item to track which items have changed, been added, or been removed. Without a unique key, React's reconciliation algorithm is inefficient, potentially leading to bugs, incorrect state, or performance issues.

The Solution

Assign a unique and stable identifier (like a database ID) to the outermost JSX element returned inside the map() callback. Do not use the array index unless the list items are static and never change order.

❌ Bad Code ✅ Good Code
jsx<ul> {items.map((item) => ( <li>{item.name}</li> // ❌ Missing key ))}</ul> jsx<ul> {items.map((item) => ( // ✅ Using a stable, unique item ID <li key={item.id}>{item.name}</li> ))}</ul>

9. Invalid Hook Call Warning

The Problem

A generalized error that often indicates a problem with your project environment:

Warning: Invalid hook call. Hooks can only be called inside the body of a function component.

The Cause

This can occur for a few reasons:

  1. Multiple React Copies: Your project/bundle might contain two copies of the react library, confusing the Hook resolver.
  2. Using Hooks outside Components: Calling a hook inside a regular JavaScript function or a class component method (must be in a functional component or custom hook).

The Solution

  1. Ensure you have one single installation of react and react-dom in your package.json. Delete node_modules and run npm install (or yarn).
  2. Only use Hooks directly within the body of a functional component or a custom hook (a function starting with use).

10. React.StrictMode Causing Side Effects Twice

The Problem

In development mode, you notice certain side effects—like state updates, console logs, or API calls—are executing twice when using useEffect.

The Cause

This is intentional behavior of the React.StrictMode component. Strict Mode runs renderers, state updates, and effects (including their cleanup functions) twice only in development to help you detect non-idempotent side effects (effects that produce different results when run multiple times).

The Solution

Treat this as a feature. Your goal is to make your effects idempotent. Always use a cleanup function (return () => {}) inside useEffect to tear down any subscriptions, intervals, or listeners when the component unmounts or before the next effect runs.

❌ Bad Code ✅ Good Code
jsxuseEffect(() => { // ❌ Missing cleanup: interval runs twice const id = setInterval(() => { console.log('Ticking'); }, 1000);}); jsxuseEffect(() => { const id = setInterval(() => { console.log('Ticking'); }, 1000); // ✅ Cleanup function stops the first interval return () => { clearInterval(id); };}, []);

11. Attempted to Import Relative Path Outside of Project

The Problem

During development or building, your bundler (like Webpack or Vite) throws an error related to file paths:

Error: Attempted to import ../../../../some/path/file.js which is outside of the project root.

The Cause

You are using a relative path (../..//) to import a file that is located outside the root directory of your React project (e.g., above the src/ folder). This is a security and configuration boundary enforced by the build tools.

The Solution

  1. Restructure: Move the imported file or module inside your project's root folder (src/).
  2. Use absolute paths/aliases: Configure your build tool (e.g., using jsconfig.json or tsconfig.json) to use path aliases. This allows you to import files using a custom root name, like import { utils } from '@utils/file'.

12. State Updates Not Reflecting Immediately

The Problem

You call a state setter function, then immediately log the state, but the logged value is the old value:

setCount(c + 1);
console.log(count); // Still shows the OLD value
Enter fullscreen mode Exit fullscreen mode

The Cause

React's state updates are asynchronous and are often batched for performance. When you call setCount(newState), React queues that update and doesn't immediately change the state variable in the current execution scope.

The Solution

  1. If you need the new state to compute the next state, use the functional update form of the setter: setCount(prevCount => prevCount + 1).
  2. If you need to perform an action after the state has definitely updated, use a useEffect hook that watches the state variable.
❌ Bad Code ✅ Good Code
jsxconst handleClick = () => { setCount(count + 1); // ❌ Logs the old count console.log(count);}; jsx// ✅ Use useEffect to react to the changeuseEffect(() => { console.log('Count is now:', count);}, [count]);

13. Uncontrolled to Controlled Input Warning

The Problem

You see a console warning when dealing with form inputs:

Warning: A component is changing an uncontrolled input of type text to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa).

The Cause

An input element starts as uncontrolled (when its value prop is undefined or null), and then later its value prop changes to a defined string. This transition confuses React's internal handling of the input state.

The Solution

Ensure that the value prop of your controlled input is always defined, even if it's an empty string initially. If the initial data is asynchronous, set the state to a default empty string.

❌ Bad Code ✅ Good Code
jsx// If user.name is undefined on first renderconst [user, setUser] = useState({}); <input value={user.name} onChange={handleChange} /> jsx// Initialize state with defined empty stringsconst [user, setUser] = useState({ name: '' }); // Value is always a string ('') or a name<input value={user.name} onChange={handleChange} />

14. Module Not Found / Import Path Error

The Problem

Your compiler or application fails to start with an error that a file or module cannot be found:

Error: Module not found: Error: Can't resolve './components/MyComponet' in '...'

The Cause

This is usually a simple typographical error, incorrect casing (file systems are case-sensitive!), or a wrong relative path in your import statement.

The Solution

  1. Check Casing: Ensure the casing of the component name and the path (MyComponent vs Mycomponent) exactly matches the file system.
  2. Verify Path: Use the correct relative path (./ for current directory, ../ for parent directory).
  3. Check Imports/Exports: Make sure the name you import matches the name it was exported as (e.g., export default UserProfile).

15. Memory Leak / Async State Update After Unmount

The Problem

The console throws a warning about setting state on an unmounted component, which is a classic symptom of a memory leak:

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application.

The Cause

This occurs when an asynchronous operation (like a setTimeout or an API fetch) finishes after the component that initiated it has been removed from the DOM, and the callback attempts to call a state setter.

The Solution

Use the useEffect cleanup function to either cancel the ongoing async task (if possible) or use a local variable (often a ref) to track the mounted state of the component.

❌ Bad Code ✅ Good Code
jsxuseEffect(() => { // Assume fetchData takes time fetchData().then(data => { // ❌ Error if component unmounts before resolve setData(data); });}, []); jsxfunction MyComponent() { const [data, setData] = useState(null); const mounted = useRef(true); useEffect(() => { // Cleanup function sets the flag to false on unmount return () => { mounted.current = false; }; }, []); fetchData().then(data => { if (mounted.current) { // ✅ Only set state if still mounted setData(data); } });}

Professional Insight: Mobile App Developers 👨‍💻

Mastering these 15 common errors is crucial for efficient React development. While many React developers focus on web applications, the same principles, state management practices, and error-handling techniques are directly applicable to building mobile apps using React Native.

The Connection to Mobile App Development

The errors discussed—from "Cannot Read Property of Undefined" (due to asynchronous data) to "Maximum Update Depth Exceeded" (infinite loops) and "Memory Leak / Async State Update After Unmount" (Error #15)—are highly relevant to React Native. In a mobile environment, a lack of cleanup or an infinite loop can lead to significant jank and app crashes.

Solution (Hiring Insight: Hire Mobile App Developers)

When you Hire React Mobile App Developers, look for those who demonstrate a deep understanding of these core React principles. A skilled React Native developer will:

  1. Prioritize Thread Safety: They know how to use Hooks correctly to avoid blocking the JavaScript thread, which is vital for smooth mobile UI interactions.
  2. Enforce Cleanups: They routinely use the return function in useEffect to clean up subscriptions and timers, preventing the memory leaks that are common in mobile environments.
  3. Optimize List Rendering: They understand the critical performance impact of key props and efficient list components (FlatList, SectionList) in mobile viewports.

Hiring developers with strong foundational React knowledge ensures your mobile application is performant, stable, and maintainable.

Top comments (0)