- Регистрация
- 1 Мар 2015
- Сообщения
- 1,481
- Баллы
- 155
Have you ever updated a file in your React + Vite project only to see full page reloads instead of fast refresh? ?
That happened to me when I built an authentication context and exported both the provider and a custom hook (useAuth) from the same .tsx file. Turns out, that’s a no-go if you want smooth Hot Module Reloading (HMR) with Vite.
Here’s what was happening and how a small refactor completely fixed it.
The Problem
I had a single AuthContext.tsx file that looked something like this:
import {
createContext,
useContext,
useState,
useEffect,
ReactNode,
} from "react";
import authApi from "@/api/auth-api";
import { User } from "@/types/users";
import { AuthContextType, AuthResponse } from "@/types/auth";
const AuthContext = createContext<AuthContextType | undefined>(undefined);
export function AuthProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<User | null>(null);
const [isLoading, setIsLoading] = useState(true);
...
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}
export function useAuth() {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error("useAuth must be used within an AuthProvider");
}
return context;
}
Vite kept logging:
The Fix
The cleanest solution: split your hook into a separate .ts file.
AuthContext.ts
import { createContext, useContext } from "react";
import type { AuthContextType } from "@/types/auth";
export const AuthContext = createContext<AuthContextType | undefined>(
undefined
);
export function useAuth() {
const ctx = useContext(AuthContext);
if (!ctx) throw new Error("useAuth must be used within <AuthProvider>");
return ctx;
}
AuthProvider.tsx
import { useState, useEffect, ReactNode } from "react";
import authApi from "@/api/auth-api";
import { User } from "@/types/users";
import { AuthResponse } from "@/types/auth";
import { AuthContext } from "@/contexts/AuthContext";
export function AuthProvider({ children }: { children: ReactNode }) {
// ... state + auth methods here ...
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}
Takeaway
If you're using Vite with React and notice weird HMR behaviour, check your exports. Keep .tsx files component-only, and move hooks or utilities into .ts files to avoid these issues.
Have you run into other quirky Vite or React dev issues? Got any lightweight performance tricks? Drop them in the comments, and let others know what’s worked for you! ?
That happened to me when I built an authentication context and exported both the provider and a custom hook (useAuth) from the same .tsx file. Turns out, that’s a no-go if you want smooth Hot Module Reloading (HMR) with Vite.
Here’s what was happening and how a small refactor completely fixed it.
The Problem
I had a single AuthContext.tsx file that looked something like this:
import {
createContext,
useContext,
useState,
useEffect,
ReactNode,
} from "react";
import authApi from "@/api/auth-api";
import { User } from "@/types/users";
import { AuthContextType, AuthResponse } from "@/types/auth";
const AuthContext = createContext<AuthContextType | undefined>(undefined);
export function AuthProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<User | null>(null);
const [isLoading, setIsLoading] = useState(true);
...
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}
export function useAuth() {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error("useAuth must be used within an AuthProvider");
}
return context;
}
Vite kept logging:
Basically, Vite's React plugin only supports Fast Refresh when your .tsx file exports components only (i.e., PascalCase components). If you export anything else — like a custom hook — it invalidates the module and reloads the whole page.hmr invalidate /src/contexts/AuthContext.tsx Could not Fast Refresh ("useAuth" export is incompatible). Learn more at
The Fix
The cleanest solution: split your hook into a separate .ts file.
AuthContext.ts
import { createContext, useContext } from "react";
import type { AuthContextType } from "@/types/auth";
export const AuthContext = createContext<AuthContextType | undefined>(
undefined
);
export function useAuth() {
const ctx = useContext(AuthContext);
if (!ctx) throw new Error("useAuth must be used within <AuthProvider>");
return ctx;
}
AuthProvider.tsx
import { useState, useEffect, ReactNode } from "react";
import authApi from "@/api/auth-api";
import { User } from "@/types/users";
import { AuthResponse } from "@/types/auth";
import { AuthContext } from "@/contexts/AuthContext";
export function AuthProvider({ children }: { children: ReactNode }) {
// ... state + auth methods here ...
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}
Takeaway
If you're using Vite with React and notice weird HMR behaviour, check your exports. Keep .tsx files component-only, and move hooks or utilities into .ts files to avoid these issues.
Have you run into other quirky Vite or React dev issues? Got any lightweight performance tricks? Drop them in the comments, and let others know what’s worked for you! ?