Code To Learn logo

Code To Learn

M7: Forms & Authentication

L2: Add AuthProvider to App

Wrap the entire application with AuthProvider

Now that we have the AuthProvider component, let's wrap our entire application with it so all components can access authentication state! 🎯

Why Wrap the App?

The AuthProvider needs to wrap the entire application because:

  1. Global access - Any component can use useAuth()
  2. Router access - Routes can check authentication
  3. Navbar access - Show/hide based on auth state
  4. API access - Add tokens to all requests

Rule: The provider must wrap everything that needs auth.

Current App Structure

src/App.jsx
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import HomePage from '@/pages/HomePage';
import FavoritesPage from '@/pages/FavoritesPage';
import NotFoundPage from '@/pages/NotFoundPage';
import Navbar from '@/components/Navbar';

function App() {
  return (
    <BrowserRouter>
      <div className="app">
        <Navbar />
        <main className="main-content">
          <Routes>
            <Route path="/" element={<HomePage />} />
            <Route path="/favorites" element={<FavoritesPage />} />
            <Route path="*" element={<NotFoundPage />} />
          </Routes>
        </main>
      </div>
    </BrowserRouter>
  );
}

export default App;

Problem: No authentication context available yet!

Add AuthProvider

Update App.jsx to wrap everything with AuthProvider:

src/App.jsx
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { AuthProvider } from '@/components/AuthProvider';
import HomePage from '@/pages/HomePage';
import FavoritesPage from '@/pages/FavoritesPage';
import NotFoundPage from '@/pages/NotFoundPage';
import Navbar from '@/components/Navbar';

function App() {
  return (
    <AuthProvider>
      <BrowserRouter>
        <div className="app">
          <Navbar />
          <main className="main-content">
            <Routes>
              <Route path="/" element={<HomePage />} />
              <Route path="/favorites" element={<FavoritesPage />} />
              <Route path="*" element={<NotFoundPage />} />
            </Routes>
          </main>
        </div>
      </BrowserRouter>
    </AuthProvider>
  );
}

export default App;

Understanding the Wrapping Order

Test the Integration

Let's verify the AuthProvider is working:

Test useAuth hook in Navbar:

Temporarily add this to Navbar to test:

src/components/Navbar.jsx
import { useAuth } from '@/components/AuthProvider';

function Navbar() {
  const { user, isLoading } = useAuth();
  
  console.log('Auth state:', { user, isLoading });
  
  // ... rest of component
}

Check browser console:

You should see:

Auth state: { user: null, isLoading: true }

This confirms:

  • useAuth() hook works
  • ✅ AuthProvider is providing context
  • ✅ Initial state is correct

Remove test code:

Remove the console.log once verified:

src/components/Navbar.jsx
import { useAuth } from '@/components/AuthProvider';

function Navbar() {
  const { user, isLoading } = useAuth();
  
  // ... rest of component (no console.log)
}

Common Mistakes

❌ Wrong: BrowserRouter outside AuthProvider

<BrowserRouter>
  <AuthProvider>
    <App />
  </AuthProvider>
</BrowserRouter>

Problem: AuthProvider can't use useNavigate() for redirects.

✅ Correct: AuthProvider outside BrowserRouter

<AuthProvider>
  <BrowserRouter>
    <App />
  </BrowserRouter>
</AuthProvider>

Result: Any component can use both auth and navigation!

❌ Wrong: useAuth without provider

// App.jsx (no AuthProvider!)
<BrowserRouter>
  <App />
</BrowserRouter>

// Navbar.jsx
function Navbar() {
  const auth = useAuth();  // ❌ ERROR!
}

Error:

Error: useAuth must be used within an AuthProvider

✅ Correct: Always wrap with provider

<AuthProvider>
  <BrowserRouter>
    <App />
  </BrowserRouter>
</AuthProvider>

❌ Wrong: Multiple AuthProviders

<AuthProvider>
  <BrowserRouter>
    <AuthProvider>  {/* ❌ Duplicate! */}
      <App />
    </AuthProvider>
  </BrowserRouter>
</AuthProvider>

Problem: Inner AuthProvider creates separate context. Components might use wrong one.

✅ Correct: Single AuthProvider

<AuthProvider>
  <BrowserRouter>
    <App />
  </BrowserRouter>
</AuthProvider>

Rule: One AuthProvider wrapping everything.

What Components Can Access Now

With AuthProvider wrapping the app, these components can now use auth:

// ✅ Navbar
const { user, signOut } = useAuth();

// ✅ HomePage
const { user, isLoading } = useAuth();

// ✅ FavoritesPage
const { user, token } = useAuth();

// ✅ Any component inside App
const auth = useAuth();  // Works anywhere!

Visual Representation

┌─────────────────────────────────────────┐
│ AuthProvider                            │
│ • Provides: user, token, isLoading      │
│ • Provides: signIn, signOut             │
│                                         │
│  ┌────────────────────────────────────┐ │
│  │ BrowserRouter                      │ │
│  │ • Provides: navigation             │ │
│  │ • Provides: useNavigate, Link      │ │
│  │                                    │ │
│  │  ┌──────────────────────────────┐ │ │
│  │  │ App                          │ │ │
│  │  │                              │ │ │
│  │  │  Navbar → uses auth ✅       │ │ │
│  │  │                              │ │ │
│  │  │  Routes                      │ │ │
│  │  │    HomePage → uses auth ✅   │ │ │
│  │  │    FavoritesPage → uses auth✅│ │ │
│  │  └──────────────────────────────┘ │ │
│  └────────────────────────────────────┘ │
└─────────────────────────────────────────┘

What's Next?

In Lesson 3, we'll:

  1. Fetch the access token when app loads
  2. Check if user has existing session
  3. Set isLoading to false after check
  4. Handle token fetch errors

✅ Lesson Complete! AuthProvider now wraps your entire application!

Key Takeaways

  • AuthProvider wraps app - Provides auth to all components
  • Order matters - AuthProvider outside BrowserRouter
  • Global access - Any component can use useAuth()
  • Test integration - Console.log confirms it works
  • One provider - Don't create multiple AuthProviders
  • Ready for next step - Foundation in place for token fetching