如何优化React Context类型定义,无需默认值且确保值始终存在
优化AuthContext类型定义方案
1. 调整Context类型定义
首先将IAuthContext中的token定义为必填的string,明确表示正常渲染子组件时token一定存在:
interface IAuthContext { token: string; }
2. 初始化Context时允许默认值为undefined
由于createContext必须传入默认值,但我们希望子组件仅在Provider提供有效token时访问Context,所以将Context类型设为IAuthContext | undefined,默认值传undefined:
export const AuthContext = createContext<IAuthContext | undefined>(undefined);
3. 封装自定义useAuth钩子
通过自定义钩子确保调用时一定能拿到有效Context,避免每次使用都要断言:
import { useContext } from 'react'; export const useAuth = () => { const context = useContext(AuthContext); if (!context) { throw new Error('useAuth 必须在 AuthProvider 内部使用'); } return context; };
这个钩子会在未找到Provider时抛出错误,TypeScript会据此推断返回值一定是IAuthContext,token自然是确定存在的string类型。
4. 修正AuthProvider逻辑
修复原代码中setToken(token)的错误(应改为setToken(authToken)),并添加加载状态避免子组件短暂渲染:
export const AuthProvider = ({ children }: { children: ReactNode }) => { const [token, setToken] = useState<string | undefined>(); const [isLoading, setIsLoading] = useState(true); const navigate = useNavigate(); useEffect(() => { const authToken = localStorage.getItem('authToken'); if (!authToken) { navigate('/login'); } else { setToken(authToken); } setIsLoading(false); }, [navigate]); // 加载中或无有效token时不渲染子组件 if (isLoading || !token) { return null; // 可替换为自定义加载动画 } return <AuthContext.Provider value={{ token }}>{children}</AuthContext.Provider>; };
5. 子组件中使用
在MyComp等子组件中直接调用useAuth()获取token,无需断言:
const MyComp = () => { const { token } = useAuth(); // token 类型为 string,可直接使用 return <div>当前token: {token}</div>; };
内容的提问来源于stack exchange,提问作者Simon Tran
相关产品推荐
相关产品推荐

