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

React中使用useContext传递语音识别状态触发无效Hook调用错误

解决React语音识别中的Invalid hook call错误

错误原因

useContext是React钩子函数,必须满足以下使用规则:

  • 只能在函数组件的顶层作用域中调用
  • 只能在自定义钩子函数中调用

你当前把useContext放在普通工具函数runSpeechRecognition里,违反了钩子的使用规则,因此触发Invalid hook call错误。

解决方案

将setListening作为参数传入工具函数,不在函数内部调用React钩子,具体修改如下:

1. 修改语音识别工具函数

移除内部的useContext相关代码,接收外部传入的setListening:

function runSpeechRecognition(setListening) {
  var SpeechRecognition = SpeechRecognition || webkitSpeechRecognition
  var recognition = new SpeechRecognition()

  recognition.onstart = function () {
    console.log('We are listening. Try speaking into the microphone.')
  }

  recognition.onspeechend = function () {
    recognition.stop()
    setListening(false)
  }

  // 添加错误处理,避免异常时状态无法重置
  recognition.onerror = function(event) {
    console.error('语音识别出错:', event.error)
    setListening(false)
  }

  recognition.start()
  setListening(true)

  return new Promise((resolve, reject) => {
    recognition.onresult = function (event) {
      var transcript = event.results[0][0].transcript
      resolve(transcript)
    }
    recognition.onerror = function(event) {
      reject(event.error)
    }
  })
}

export default runSpeechRecognition

2. 在组件中调用工具函数

在函数组件中通过useContext获取setListening,并作为参数传给工具函数:

import { useContext } from 'react'
import AppContext from './AppContext'
import runSpeechRecognition from './runSpeechRecognition'

function SpeechControlButton() {
  const { listening, setListening } = useContext(AppContext)

  const handleStartRecognition = async () => {
    try {
      const transcript = await runSpeechRecognition(setListening)
      // 处理识别得到的文本
      console.log('识别结果:', transcript)
    } catch (err) {
      console.error('识别失败:', err)
    }
  }

  return (
    <button
      onClick={handleStartRecognition}
      style={{
        backgroundColor: listening ? '#e53935' : '#2196f3',
        color: '#fff',
        border: 'none',
        padding: '10px 20px',
        borderRadius: '4px',
        cursor: 'pointer'
      }}
    >
      {listening ? '正在监听...' : '开始语音识别'}
    </button>
  )
}

export default SpeechControlButton

补充说明

通过这种方式,既遵守了React钩子的使用规范,又能正常更新listening状态来切换按钮样式,同时添加错误处理可以避免异常情况下按钮一直显示"正在监听"的状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 03:25:28