React输入框值变更时双函数执行异常:Interval调用的fetchTrans未使用最新MeetingID参数
问题根源分析
你遇到的核心问题是MeetingID不是React状态变量,而是用var声明的普通变量。React组件只会在状态或props变化时重新渲染,普通变量的变更不会触发组件更新,这就导致useEffect里的定时器一直捕获的是初始的MeetingID值,永远不会更新。另外你的输入框也不是受控组件,value绑定的是非状态变量,会导致输入显示异常。
修复步骤
这里是具体的修改方案,我会一步步说明:
- 把MeetingID改成React状态:用
useState替代var,这样变更时会触发组件重新渲染,所有依赖它的地方都会拿到最新值。 - 修正输入框为受控组件:将输入框的
value绑定到状态变量,onChange时更新状态。 - 让useEffect依赖MeetingID:这样当MeetingID变化时,会自动清除旧的定时器,创建新的定时器,确保定时器里的
fetchTrans使用最新的MeetingID。 - 修正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
相关产品推荐
相关产品推荐

