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:
- Global access - Any component can use
useAuth() - Router access - Routes can check authentication
- Navbar access - Show/hide based on auth state
- API access - Add tokens to all requests
Rule: The provider must wrap everything that needs auth.
Current App Structure
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:
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:
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:
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:
- Fetch the access token when app loads
- Check if user has existing session
- Set
isLoadingtofalseafter check - 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