This error occurs when a component calls useContext but is not wrapped by the corresponding Context Provider in the component tree. The context value defaults to undefined when no Provider is found above the component.
This error indicates that you're trying to consume a React Context value using the useContext hook, but the component is not a descendant of the corresponding Context Provider in the component tree. When you create a context with React.createContext(), you get a Provider component that supplies the context value to its descendants. If you call useContext() in a component that isn't wrapped by this Provider (or is outside its subtree), React returns the default value passed to createContext() - which is often undefined if no default was specified. This is React's way of telling you that the component hierarchy is incorrect and the context connection is broken. The error commonly appears during development when restructuring components or when accidentally placing a component outside the Provider wrapper.
First, check that your Provider actually wraps the component trying to use the context. Use React DevTools to inspect the component tree:
// ❌ WRONG - Consumer is outside Provider
function App() {
return (
<>
<Header /> {/* ❌ Can't access context */}
<MyContextProvider>
<Main />
</MyContextProvider>
</>
);
}
// ✅ CORRECT - All consumers inside Provider
function App() {
return (
<MyContextProvider>
<Header /> {/* ✅ Can access context */}
<Main />
</MyContextProvider>
);
}Open React DevTools, find your component, and verify the Provider appears as an ancestor in the component hierarchy.
Move the Provider to wrap all components that need access to the context. Place it as high as necessary in the tree:
// src/App.tsx
import { AuthProvider } from './contexts/AuthContext';
function App() {
return (
<AuthProvider>
{/* All components here can access AuthContext */}
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/profile" element={<Profile />} />
</Routes>
</Router>
</AuthProvider>
);
}If you need multiple contexts, nest the Providers:
<AuthProvider>
<ThemeProvider>
<DataProvider>
<App />
</DataProvider>
</ThemeProvider>
</AuthProvider>Add runtime validation to catch missing Provider errors early:
// src/contexts/AuthContext.tsx
import { createContext, useContext, ReactNode } from 'react';
interface AuthContextType {
user: User | null;
login: (email: string, password: string) => Promise<void>;
logout: () => void;
}
// Create context with undefined as initial value
const AuthContext = createContext<AuthContextType | undefined>(undefined);
export function AuthProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<User | null>(null);
const value = {
user,
login: async (email, password) => { /* ... */ },
logout: () => setUser(null),
};
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}
// Custom hook that throws if used outside Provider
export function useAuth() {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error('useAuth must be used within an AuthProvider');
}
return context;
}Now use useAuth() instead of useContext(AuthContext) to get helpful error messages.
While not fixing the root cause, providing a default value prevents undefined errors:
// Option 1: Provide actual default values
const ThemeContext = createContext<ThemeContextType>({
theme: 'light',
toggleTheme: () => {
console.warn('toggleTheme called outside Provider');
},
});
// Option 2: Make context optional and handle null case
const UserContext = createContext<UserContextType | null>(null);
export function useUser() {
const context = useContext(UserContext);
// Allow null, but throw if undefined (wrong context)
if (context === undefined) {
throw new Error('useUser must be used within UserProvider');
}
return context; // Can be null, which is valid
}Note: This approach allows code to run without Provider, which may hide problems. The custom hook pattern (Step 3) is generally preferred.
If you have multiple versions of the same context file (common with symlinks or monorepos), React sees them as different objects:
# Check for duplicate imports
npm ls react
# or
pnpm list react
# If you see multiple React versions, dedupe:
npm dedupe
# or
pnpm dedupeEnsure you're importing from one source:
// ❌ DON'T create context in multiple files
// src/contexts/AuthContext.tsx
export const AuthContext = createContext(...);
// src/components/Header.tsx
export const AuthContext = createContext(...); // ❌ Different object!
// ✅ DO import from single source
import { AuthContext } from '@/contexts/AuthContext';Provider Placement Strategy: Place Providers at the highest common ancestor of all components that need the context. Over-wrapping (placing too high) causes unnecessary re-renders; under-wrapping causes undefined errors. Use React.memo() on child components if you wrap at root level.
Context Splitting: If only some components need certain context values, split contexts to avoid prop drilling while keeping re-renders minimal:
// Instead of one large context
<UserProvider> {/* Only wrap auth-related components */}
<AuthenticatedApp />
</UserProvider>
<ThemeProvider> {/* Wrap entire app for theme */}
<App />
</ThemeProvider>TypeScript Best Practices: Always type your context and use the custom hook pattern to enforce Provider usage at compile time:
const MyContext = createContext<MyType | undefined>(undefined);
export function useMyContext(): MyType { // Return non-null type
const ctx = useContext(MyContext);
if (!ctx) throw new Error('Missing Provider');
return ctx; // TypeScript knows this is MyType, not undefined
}Testing Considerations: When testing components that use context, always wrap them in the Provider:
import { render } from '@testing-library/react';
import { AuthProvider } from '@/contexts/AuthContext';
test('renders user profile', () => {
render(
<AuthProvider>
<ProfileComponent />
</AuthProvider>
);
});Server Components (Next.js 13+): Context Providers must be Client Components. Create a separate providers.tsx file with "use client" directive:
// app/providers.tsx
'use client';
export function Providers({ children }: { children: React.ReactNode }) {
return (
<ThemeProvider>
<AuthProvider>
{children}
</AuthProvider>
</ThemeProvider>
);
}
// app/layout.tsx (Server Component)
import { Providers } from './providers';
export default function RootLayout({ children }) {
return (
<html>
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}React Hook useCallback has a missing dependency: 'variable'. Either include it or remove the dependency array react-hooks/exhaustive-deps
React Hook useCallback has a missing dependency
Cannot use private fields in class components without TS support
Cannot use private fields in class components without TS support
Cannot destructure property 'xxx' of 'undefined'
Cannot destructure property of undefined when accessing props
useNavigate() may be used only in the context of a <Router> component.
useNavigate() may be used only in the context of a Router component
Cannot find module or its corresponding type declarations
How to fix "Cannot find module or type declarations" in Vite