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

React输入框值变更时双函数执行异常:Interval调用的fetchTrans未使用最新MeetingID参数

问题根源分析

你遇到的核心问题是MeetingID不是React状态变量,而是用var声明的普通变量。React组件只会在状态或props变化时重新渲染,普通变量的变更不会触发组件更新,这就导致useEffect里的定时器一直捕获的是初始的MeetingID值,永远不会更新。另外你的输入框也不是受控组件,value绑定的是非状态变量,会导致输入显示异常。

修复步骤

这里是具体的修改方案,我会一步步说明:

  1. 把MeetingID改成React状态:用useState替代var,这样变更时会触发组件重新渲染,所有依赖它的地方都会拿到最新值。
  2. 修正输入框为受控组件:将输入框的value绑定到状态变量,onChange时更新状态。
  3. 让useEffect依赖MeetingID:这样当MeetingID变化时,会自动清除旧的定时器,创建新的定时器,确保定时器里的fetchTrans使用最新的MeetingID。
  4. 修正fetchTrans的参数传递:确保每次调用fetchTrans时都传入最新的MeetingID,避免依赖全局变量。
完整修复后的代码
function MyEditor({ signOut, user }){ 
  const[value,setValue]=React.useState([]); 
  // 1. 将MeetingID改为React状态
  const [meetingID, setMeetingID] = React.useState('');

  const txnMutation: any = value.map((txn, i) => { 
    return `mutation${i}: deleteDatamodel(input: {id: "${txn.id}"}) { id }`; 
  }); 

  // 2. 添加meetingID到useEffect依赖数组,状态变化时重建定时器
  useEffect(()=>{ 
    // 如果meetingID为空,不执行请求(可选,根据需求调整)
    if (!meetingID) return;

    // 先执行一次请求
    fetchTrans(meetingID); 
    const intervalId = setInterval(()=>{ 
      fetchTrans(meetingID); 
    },1000); 

    return () => clearInterval(intervalId); 
  },[meetingID]); // 依赖meetingID,状态变化时重新运行

  async function fetchTrans(currentMeetingID) { 
    try { 
      // 3. 使用传入的currentMeetingID,避免依赖外部变量
      const querysort = {
        sortDirection : 'ASC',
        type : 'datamodel',
        filter: {MeetingID:{eq: currentMeetingID}}
      }; 
      const transData = await API.graphql(graphqlOperation(datamodel, querysort)); 
      console.log(transData); 
      const datamodels = transData.data.datamodel.items; 
      setValue(datamodels); 
    } catch (err) { 
      console.log('error fetching transcription:', err); 
    } 
  } 

  async function handleDelete(){ 
    const deleteData = await API.graphql(graphqlOperation(` 
      mutation batchMutation { 
        ${txnMutation} 
      } 
    `)); 
    console.log(deleteData); 
  } 

  async function getstring(){ 
    // 修正原代码逻辑错误:textToHighlight初始未定义的问题
    const textToHighlight = value.sort((a, b) => a.id - b.id)
      .map(transcript => transcript.Transcription)
      .join('');
    // 可在这里使用textToHighlight,比如返回或设置状态
  } 

  const set = new Set(["tech", "deck", "Financial","select","post","social","Sometimes","sick","mad"]); 
  const arr = value.sort((a, b) => a.id - b.id); 

  // 4. 修正输入框的change事件,更新状态
  const handleUserInputChange = (e) => { 
    const newMeetingID = e.target.value; // 原代码误用了e.target.name,这里改为value
    setMeetingID(newMeetingID);
    // 不需要手动调用fetchTrans,useEffect会在meetingID变化时自动触发
  }; 

  function createMarkup(transcript) { 
    const words = ["tech", "deck", "financial","test","this is a test transcription","Tech-Debt","Look","Sometimes","together","negotiate","market"]; 
    let str = `${transcript.createdAt} ${transcript.Transcription}`; 
    words.forEach((word) => { 
      if (str.includes(word)) { 
        str = str.replaceAll(word, `<span style="color:red;font-weight:bold">${word}</span>`); 
      } 
    }); 
    return { __html: str }; 
  } 

  return <RightWrapper> 
    <Header> 
      <Button onClick={handleDelete}>Delete Transcription</Button> 
      <Button onClick={signOut}>Sign out</Button> 
      {/* 5. 输入框绑定状态变量,变成受控组件 */}
      <input 
        type="text" 
        placeholder="Meeting ID" 
        value={meetingID} 
        onChange={handleUserInputChange}
      /> 
    </Header> 
    {arr.map((transcript) => ( 
      <p dangerouslySetInnerHTML={createMarkup(transcript)} key={transcript.id} ></p> 
    ))} 
  </RightWrapper>; 
}
额外说明
  • 我修正了handleUserInputChange里的e.target.name为e.target.value,因为你要获取的是输入框的内容,不是name属性。
  • 添加了空值判断,当MeetingID为空时不执行请求,避免无效的API调用。
  • 修正了getstring函数里的逻辑错误,原代码中textToHighlight初始未定义就进行拼接,会导致控制台报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 21:27:30