You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript创建AuthContext与useReducer报错及Hook调用异常求解

问题原因及解决方案

1. 类型定义不匹配导致的TS编译报错

错误根源

  • 你创建AuthContext时指定的泛型是IState,但实际给Provider传递的value是包含state和dispatch的对象,二者类型完全不匹配,这是Provider行报错的直接原因
  • AuthReducer没有处理default分支,且LOGOUT操作返回的状态缺失user和token字段,导致函数可能返回undefined,不符合useReducer要求的reducer必须始终返回完整state的规则,这是useReducer行报错的直接原因
  • initialState的user和token是字符串空值,和IState定义的string | null类型不兼容

修复后的AuthContext代码

import { createContext, ReactNode, useReducer, Dispatch } from 'react'
import { AuthReducer } from './Reducer';

export interface IState {
    isAuthenticated: boolean
    user: string | null
    token: string | null
}

// reducer action 接口定义
export interface IAction {
    type: 'LOGIN' | 'LOGOUT' | 'REGISTER' | 'FORGOT PASSWORD'
    payload?: any
}

// 新增Context的实际类型定义
interface IAuthContextType {
    state: IState
    dispatch: Dispatch<IAction>
}

interface IAuthProvider {
    children: ReactNode
}

const initialState: IState = {
    isAuthenticated: false,
    user: null,
    token: null
}

// 用正确的类型创建Context,默认值可以用类型断言占位
export const AuthContext = createContext<IAuthContextType>({} as IAuthContextType);


export const AuthProvider = ({ children }: IAuthProvider) => {
    const [state, dispatch] = useReducer(AuthReducer, initialState)

    return (
        <AuthContext.Provider value={{ state, dispatch }}>
            {children}
        </AuthContext.Provider>
    )
}

修复后的Reducer代码

import { IAction, IState } from ".";

export const AuthReducer = (state: IState, action: IAction): IState => {
    switch (action.type) {
        case 'LOGIN':
            localStorage.setItem("user", action.payload.user)
            localStorage.setItem("token", action.payload.token)
            return {
                ...state,
                isAuthenticated: true,
                user: action.payload.user,
                token: action.payload.token
            }
        case 'LOGOUT':
            localStorage.clear()
            return {
                ...state,
                isAuthenticated: false,
                // 补全缺失字段,符合IState类型要求
                user: null,
                token: null
            }
        // 新增default分支,未匹配到的action直接返回当前state
        default:
            return state
    }
}

2. 登录页Hook调用报错

错误根源

90%以上的这类报错在确认符合Hook规则的情况下,都是因为使用AuthContext的组件没有被包裹在AuthProvider的子节点中。useContext只能获取对应Provider上层提供的上下文,如果你没有在外层包裹AuthProvider,就会触发异常。其次如果IProps未定义也可能导致组件识别异常。

修复方案

  • 首先在根组件(比如App.tsx或者main.tsx)中用AuthProvider包裹所有需要用到用户状态的组件,示例:
// main.tsx 示例
import React from 'react'
import ReactDOM from 'react-dom/client'
import { AuthProvider } from './AuthContext'
import { Login } from './Login'
import App from './App'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <AuthProvider>
      {/* 所有子组件都可以正常使用AuthContext */}
      <App />
      <Login />
    </AuthProvider>
  </React.StrictMode>,
)
  • 补充登录页缺失的IProps定义,或者如果组件没有props直接去掉泛型即可,修复后的登录页代码:
import React, { FC, useContext } from 'react'
import { AuthContext } from '../AuthContext'

// 无props的话可以直接写FC,不需要加IProps泛型
export const Login: FC = () => {
    const { state, dispatch } = useContext(AuthContext)
    const login = () => {
        dispatch({
            type: 'LOGIN',
            // 这里payload要按实际业务传user和token,你原来的写法不符合reducer的处理逻辑
            payload: { user: 'testUser', token: 'testToken' }
        })
    }
    return (
        <div>
            <input name="username" />
            <button onClick={login}>登录</button>
        </div>
    )
}
  • 如果以上操作后还报错,检查package.json中的react、react-dom、@types/react、@types/react-dom版本是否一致,删除node_modules和lock文件重新安装即可。

内容的提问来源于stack exchange,提问作者frsnmk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 09:54:03