Top 10 Mistakes in React.js and How to Avoid Them

React.js is one of the most popular front-end libraries for building modern web applications. However, many developers—especially beginners—often make common mistakes that lead to performance issues, poor maintainability, and bugs.

In this article, we’ll explore the top 10 mistakes in React.js and how to avoid them with best practices and code examples.

1️⃣ Mutating State Directly Instead of Using setState()

Mistake: Modifying State Directly

const [count, setCount] = useState(0);

const increment = () => {
    count += 1;  // ❌ Directly modifying state
};

Issue:

  • React does not detect the state change, so the component does not re-render.

Solution: Use setState() to Update State Properly

const [count, setCount] = useState(0);

const increment = () => {
    setCount(prevCount => prevCount + 1);  // ✅ Correct way
};

Benefit: Ensures React re-renders the component properly.

2️⃣ Using index as a Key in Lists

Mistake: Using Array Index as Key

{items.map((item, index) => (
    <li key={index}>{item.name}</li>  // ❌ Bad practice
))}

Issue:

  • If items are reordered, React cannot track changes properly, leading to unexpected UI behavior.

Solution: Use a Unique Identifier as a Key

{items.map(item => (
    <li key={item.id}>{item.name}</li>  // ✅ Correct way
))}

Benefit: Prevents unnecessary re-renders and ensures better list tracking.

3️⃣ Overusing State Instead of Using Props or Context API

Mistake: Managing Global Data in Local State

const [theme, setTheme] = useState("light"); // ❌ Managing global theme locally

Issue:

  • Makes it difficult to share data across multiple components.

Solution: Use Context API for Global State

const ThemeContext = createContext();

const ThemeProvider = ({ children }) => {
    const [theme, setTheme] = useState("light");
    return (
        <ThemeContext.Provider value={{ theme, setTheme }}>
            {children}
        </ThemeContext.Provider>
    );
};

Benefit: Makes data sharing across components easier.

4️⃣ Not Using useEffect Dependencies Properly

Mistake: Forgetting the Dependency Array

useEffect(() => {
    console.log("Component Mounted!");
}); // ❌ Will run on every render

Issue:

  • This runs on every render, causing performance issues.

Solution: Provide Dependency Array

useEffect(() => {
    console.log("Component Mounted!");
}, []); // ✅ Runs only once

Benefit: Avoids unnecessary re-executions, improving performance.

5️⃣ Overusing useEffect for State Changes

Mistake: Updating State Inside useEffect Without a Condition

useEffect(() => {
    setData(fetchData());  // ❌ Infinite loop risk
}, [data]);

Issue:

  • This can cause an infinite loop if not handled properly.

Solution: Use Conditions or Memoization

useEffect(() => {
    setData(fetchData());
}, []); // ✅ Runs only once

Benefit: Prevents unnecessary re-renders and infinite loops.

6️⃣ Not Memoizing Expensive Calculations (useMemo)

Mistake: Performing Expensive Calculations in Render

const result = heavyCalculation(data); // ❌ Runs on every render

Issue:

  • Recalculates on every render, causing performance issues.

Solution: Use useMemo() to Optimize Performance

const result = useMemo(() => heavyCalculation(data), [data]); // ✅ Optimized

Benefit: Caches the result, reducing unnecessary computations.

7️⃣ Using useEffect Instead of useMemo or useCallback

Mistake: Using useEffect for Derived State

const [filteredItems, setFilteredItems] = useState([]);

useEffect(() => {
    setFilteredItems(items.filter(item => item.active));
}, [items]); // ❌ Unnecessary state updates

Issue:

  • Triggers unnecessary re-renders.

Solution: Use useMemo Instead

const filteredItems = useMemo(() => items.filter(item => item.active), [items]); // ✅ Optimized

Benefit: Prevents unnecessary state updates.

8️⃣ Forgetting to Cleanup Effects in useEffect

Mistake: Not Cleaning Up Event Listeners

useEffect(() => {
    window.addEventListener("resize", handleResize);
}, []); // ❌ Event listener never removed

Issue:

  • Leads to memory leaks.

Solution: Cleanup with Return Function

useEffect(() => {
    const handleResize = () => console.log("Resized!");
    window.addEventListener("resize", handleResize);
    
    return () => {
        window.removeEventListener("resize", handleResize); // ✅ Cleanup
    };
}, []);

Benefit: Prevents memory leaks and ensures proper event handling.

9️⃣ Using Anonymous Functions in useEffect Dependencies

Mistake: Passing Functions Directly as Dependencies

useEffect(() => {
    fetchData();
}, [fetchData]); // ❌ Triggers effect on every render

Issue:

  • Creates a new function reference on every render, triggering useEffect unnecessarily.

Solution: Use useCallback to Memoize Functions

const fetchData = useCallback(() => {
    // API call
}, []);

useEffect(() => {
    fetchData();
}, [fetchData]); // ✅ Function reference remains stable

Benefit: Prevents unnecessary effect executions.

🔟 Not Lazy Loading Components (React.lazy())

Mistake: Importing All Components at Once

import Dashboard from "./Dashboard";  
import Profile from "./Profile";  

Issue:

  • Increases initial page load time.

Solution: Use Lazy Loading for Performance Optimization

const Dashboard = React.lazy(() => import("./Dashboard"));
const Profile = React.lazy(() => import("./Profile"));

<Suspense fallback={<div>Loading...</div>}>
    <Dashboard />
</Suspense>

Benefit: Improves page speed by loading components only when needed.

🎯 Conclusion

React is powerful but also tricky to master. By avoiding these common mistakes, you can build faster, scalable, and maintainable applications.

Use setState() instead of modifying state directly
Avoid using array index as keys in lists
Use Context API instead of unnecessary local state
Optimize performance with useMemo and useCallback
Ensure proper effect cleanup in useEffect
Use lazy loading for better performance

By following these best practices, you’ll write better React code and build high-performing applications! 🚀

Comments

Spring Boot 3 Paid Course Published for Free
on my Java Guides YouTube Channel

Subscribe to my YouTube Channel (165K+ subscribers):
Java Guides Channel

Top 10 My Udemy Courses with Huge Discount:
Udemy Courses - Ramesh Fadatare