反应忽略事件,直到 setState 完成设置 usestate

Posted

技术标签:

【中文标题】反应忽略事件,直到 setState 完成设置 usestate【英文标题】:React ignore event until setState finished setting the usestate 【发布时间】:2021-05-17 03:14:50 【问题描述】:

我必须将笔记与麦克风检测到的传入笔记相匹配。我正在使用 fft 来检测音高并将其与下一个最接近的音符相匹配。它以大约 10x/s 的速度触发 handleNoteEvent。问题是因为 setNote 多次异步 if 语句 == true ,直到 setState 完成设置随后导致应用程序多次重新呈现的值。在使用 React 钩子时如何等到 setState 完成? (currentNote 被多个孩子使用)

编辑:如果我正确理解文档,带有钩子的setState 似乎不会返回承诺或接受回调

编辑 2:我想我必须澄清我的问题:我需要在 if 变为 true 后忽略传入的事件,直到 setState 完成将 currentNote 设置为新的 note 对象。

function App() 
const [currentNote, setNote] = useState(new Note());

//Event handler that gets the event from the fft tuner multiple times a second
const handleNoteEvent = (fftNote) => 
    if (currentNote == fftNote)) 
      console.log('match');
      nextNote();
    
//The problem here is the nextNote() is fired multiple times since setNote is async. How can I ignore all incoming events while setNote is not finished?
const nextNote = () => setNote(new Note());
...

【问题讨论】:

这能回答你的问题吗? React.js, wait for setState to finish before triggering a function? 这不适用于功能组件。功能组件中的 setState 不接受第二个参数。 setNote 是如何变成异步的? AFAIK,setNote 是同步的,因为它是 React useState hook。 嗯,当前音符的值仅在大约 500 毫秒后才改变,这就是为什么我认为它是异步的 是不是因为Note构造函数很贵? 【参考方案1】:

好吧,我现在所拥有的东西在实现音符变化时的 useEffect 时应该可以正常工作。 这似乎是一个相当肮脏的解决方案,如果有人能告诉我如何更干净,我将不胜感激:

const [currentNote, setNote] = useState(new Note());
var waiting = false;
const handleNoteEvent = (receivedNote) => 
    if ((currentNote == receivedNote) && !waiting) 
      waiting = true;
      setNote(new Note());
    
  ;
  useEffect(() => 
    waiting = false;
  , [currentNote]);

【讨论】:

【参考方案2】:

您必须处理在另一个useEffect 中的setNote 之后发生的事情。类似的东西:

React.useEffect(() => 
  // Triggered only once when your component mounts (= componentDidMount in class component)
, []);

React.useEffect(() => 
  // It is only triggered when not changes.
  // Do your things after setting notes here.
  // Be careful about looping. If you set note here, you'll need to check the value as you did in your exemple to prevent updating note indefinitely
, [note]);

一般来说,您不限于一种 useEffect 或一种钩子。如果需要,使用多个 useStateuseEffect 拆分您的任务。

【讨论】:

哦,谢谢,我会尽快尝试。我已经尝试过了,但是遇到了您提到的递归问题。如果我检查那里的状态,它已经完成设置了吗? 是的,这是 useEffect 中依赖项的目的,它在 deps 更改后触发。 好吧,不幸的是,这仍然给我留下了同样的问题,因为我的事件被触发了多次,我不知道如何忽略它 @Nils 您的支票可能有问题,无法区分两个音符。如果没有setNote 触发(所以如果currentNote !== ffNote)则不会触发以currentNote 为依赖的useEffect。 useEffect的问题是,我设置了note之后没有触发任何函数。只是将 currentNote 传递给一个孩子,然后绘制一个新的笔记。它应该忽略 fft 输入的注释,直到一切都完成渲染

以上是关于反应忽略事件,直到 setState 完成设置 usestate的主要内容,如果未能解决你的问题,请参考以下文章

对 useEffect 挂钩内的多个 setState() 调用做出反应批量更新

用动态键反应 setState

反应对象的本机 setState/useState

无法在反应组件中使用 setState

setState 有条件地做出反应

在 componentDidMount 上反应本机 setState 不起作用