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

TS React中useContext失效,出现无效Hook调用错误求助

解决React Context的无效Hook调用错误

错误根源

你在React.createContext的默认值中直接调用了useSharedValue这个Hook,这违反了React Hook的核心规则:Hook只能在React组件函数的顶层、或自定义Hook的顶层调用,不能在模块全局作用域、普通函数里执行。createContext是在模块加载时就运行的,此时根本不在React的组件渲染流程中,所以会触发"无效Hook调用"错误。

修复步骤

  1. 修正Context的默认值定义
    把默认值里的useSharedValue调用替换为符合类型的占位值,避免在全局作用域调用Hook:

    // types.ts
    type Score = {
      correct: number;
      incorrect: number;
    };
    
    export type ReactQuizContextType = {
      check: SharedValue<string>;
      activeIndex: SharedValue<number>;
      direction: SharedValue<string>;
      redo: boolean;
      setRedo: React.Dispatch<React.SetStateAction<boolean>>;
      score: Score;
      setScore: React.Dispatch<React.SetStateAction<Score>>;
    };
    
    // 用类型断言给SharedValue设置符合结构的占位值,避免调用Hook
    export const ReactQuizContext = React.createContext<ReactQuizContextType>({
      check: { value: "wrong" } as SharedValue<string>,
      activeIndex: { value: 0 } as SharedValue<number>,
      direction: { value: "vertical" } as SharedValue<string>,
      redo: false,
      setRedo: () => {},
      score: { correct: 0, incorrect: 0 },
      setScore: () => {},
    });
    
    export const useReactQuizContext = () => React.useContext(ReactQuizContext);
    
  2. 在Provider所在组件内创建Hook值
    所有需要注入Context的Hook(useSharedValue、useState等),必须在Provider所在的组件内部顶层创建,确保在React渲染流程中调用:

    // ReactQuiz组件
    const ReactQuiz = () => {
      // 在此处创建所有Context需要的Hook值
      const check = useSharedValue("wrong");
      const activeIndex = useSharedValue(0);
      const direction = useSharedValue("vertical");
      const [redo, setRedo] = React.useState(false);
      const [score, setScore] = React.useState<Score>({ correct: 0, incorrect: 0 });
    
      // 其他业务逻辑示例
      const onCorrect = () => {
        setScore(prev => ({ ...prev, correct: prev.correct + 1 }));
      };
    
      const onIncorrect = () => {
        setScore(prev => ({ ...prev, incorrect: prev.incorrect + 1 }));
      };
    
      return (
        <ReactQuizContext.Provider
          value={{ score, setScore, redo, setRedo, activeIndex, direction, check }}
        >
          <GestureHandlerRootView style={styles.container}>
            <StatusBar style="auto" hidden />
            <GestureDetector gesture={Gesture.Exclusive(flingUp, flingDown)}>
              <View style={[styles.dataContainer]} pointerEvents="box-none">
                {data.map((item, index) => (
                  <Card
                    info={item}
                    key={item.id}
                    index={index}
                    activeIndex={activeIndex}
                    totalLength={data.length - 1}
                    direction={direction}
                    onCorrect={onCorrect}
                    onIncorrect={onIncorrect}
                  />
                ))}
              </View>
            </GestureDetector>
          </GestureHandlerRootView>
        </ReactQuizContext.Provider>
      );
    };
    

额外提醒

  • 确保所有使用useReactQuizContext的组件,都被ReactQuizContext.Provider包裹,否则会拿到默认的占位值,可能导致异常。
  • 若想避免误用默认值,可以把Context类型改为可选,然后在自定义Hook里做校验:
    export const ReactQuizContext = React.createContext<ReactQuizContextType | undefined>(undefined);
    
    export const useReactQuizContext = () => {
      const context = React.useContext(ReactQuizContext);
      if (!context) {
        throw new Error("useReactQuizContext must be used within a ReactQuizContext.Provider");
      }
      return context;
    };
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 20:47:28