Code To Learn logo

Code To Learn

M3: Effects & Data

L9: M3 Review

Comprehensive review of useEffect, side effects, and async data patterns

Congratulations on completing Module 3! Let's review everything you've learned about useEffect, side effects, and handling asynchronous data in React.

What You've Learned

Over the past 8 lessons, you've mastered:

Core Concepts

  • useEffect hook - Running side effects in functional components
  • Dependency arrays - Controlling when effects run
  • Async/await - Handling asynchronous operations in React
  • Data fetching - Loading data from APIs
  • Loading states - Showing feedback during async operations
  • Error handling - Gracefully handling failures
  • Cleanup functions - Preventing memory leaks and race conditions
  • Custom hooks - Extracting and reusing logic

Practical Skills

  • Built a mock API for development
  • Implemented data fetching with proper state management
  • Created reusable UI components (Spinner, ErrorMessage, ImageCarousel)
  • Handled edge cases and error scenarios
  • Used AbortController for request cancellation
  • Refactored complex components with custom hooks

useEffect Patterns Quick Reference

Common useEffect Pitfalls

Learn from these common mistakes!

When to Use useEffect

✅ Use useEffect for:

  1. Data fetching

    useEffect(() => {
      fetchData();
    }, []);
  2. Subscriptions

    useEffect(() => {
      const sub = api.subscribe(callback);
      return () => sub.unsubscribe();
    }, []);
  3. Timers

    useEffect(() => {
      const id = setTimeout(doSomething, 1000);
      return () => clearTimeout(id);
    }, []);
  4. DOM manipulation

    useEffect(() => {
      document.title = `Page: ${page}`;
    }, [page]);
  5. Event listeners

    useEffect(() => {
      window.addEventListener('resize', handleResize);
      return () => window.removeEventListener('resize', handleResize);
    }, []);
  6. Syncing with external systems

    useEffect(() => {
      map.setCenter(coordinates);
    }, [coordinates]);

❌ DON'T use useEffect for:

  1. Derived state (calculate during render)

    // ❌ Don't
    useEffect(() => {
      setTotal(price * quantity);
    }, [price, quantity]);
    
    // ✅ Do
    const total = price * quantity;
  2. Event handlers (use event handler functions)

    // ❌ Don't
    useEffect(() => {
      if (clicked) handleClick();
    }, [clicked]);
    
    // ✅ Do
    <button onClick={handleClick}>Click</button>
  3. Transforming data for render (transform during render)

    // ❌ Don't
    useEffect(() => {
      setFilteredUsers(users.filter(u => u.active));
    }, [users]);
    
    // ✅ Do
    const filteredUsers = users.filter(u => u.active);
  4. Initializing state (use default state or useMemo)

    // ❌ Don't
    useEffect(() => {
      setInitialData(expensiveComputation());
    }, []);
    
    // ✅ Do
    const [data] = useState(() => expensiveComputation());

Best Practices Summary

useEffect Best Practices

  1. Always specify dependencies - Include every value used in the effect
  2. Always clean up - Return cleanup function for timers, subscriptions, requests
  3. Use functional updates - Use setState(prev => ...) for state in dependencies
  4. Keep effects focused - One effect per concern, split complex effects
  5. Handle loading/error states - Always show feedback to users
  6. Cancel requests - Use AbortController for fetch requests
  7. Avoid race conditions - Use cleanup flags or AbortController
  8. Consider custom hooks - Extract reusable logic into custom hooks

Data Fetching Pattern Checklist

When implementing data fetching, make sure you:

  • ✅ Use useEffect with empty array for initial fetch
  • ✅ Add isLoading state that starts as true
  • ✅ Add error state for error handling
  • ✅ Wrap fetch in async function inside effect
  • ✅ Use try/catch/finally for proper error handling
  • ✅ Set isLoading = false in finally block
  • ✅ Clear previous errors before new fetch
  • ✅ Add cleanup function with AbortController
  • ✅ Check for AbortError in catch block
  • ✅ Show loading UI while fetching
  • ✅ Show error UI with retry option if failed
  • ✅ Handle empty results gracefully

Module 3 Component Architecture

Here's how the components we built fit together:

HomePage
├── Spinner (loading state)
├── ErrorMessage (error state)
└── PropertyCard (for each listing)
    └── ImageCarousel (image display)
        ├── Navigation buttons
        └── Slide indicators

Custom Hooks
├── useFetchListings (data fetching logic)
└── useFilteredListings (filtering logic)

API Layer
└── mockApi.js
    ├── getAllListings()
    ├── getListingById()
    ├── searchListings()
    └── filterListings()

Self-Assessment Quiz

Test your understanding! Try to answer these before expanding:

What You Can Build Now

With Module 3 complete, you can build:

  • 📱 Data-driven applications with API fetching
  • 🎨 Interactive components with timers and animations
  • 🔄 Auto-updating UIs with subscriptions
  • 🎠 Image carousels and sliders
  • 🔍 Search interfaces with debouncing
  • 📊 Dashboards with real-time data
  • 🎯 Forms with validation and async submission

Preview: Module 4 - React Router

In the next module, you'll learn:

  • Client-side routing - Building multi-page SPAs
  • Route parameters - Dynamic URLs like /listing/:id
  • Nested routes - Complex page layouts
  • Navigation - Links, redirects, and programmatic navigation
  • Route protection - Authentication and guards
  • Data loading - Fetching data based on routes

Get ready to build a complete multi-page booking application!

You've Mastered useEffect!

You now understand:

  • How side effects work in React
  • When and how to use useEffect
  • How to handle async data properly
  • How to prevent common bugs (race conditions, memory leaks)
  • How to write clean, reusable code with custom hooks

Take the Module Challenge next to solidify these skills!

What's Next?

Ready to test your knowledge? The Module 3 Challenge awaits!

You'll build a complete feature that combines everything from this module:

  • Data fetching with loading and error states
  • Pagination for browsing listings
  • Refresh button with proper cleanup
  • Response caching to reduce API calls
  • Bonus challenges: infinite scroll, search debouncing, optimistic updates

This is your chance to prove you've mastered React effects and async data!