当前位置: 首页 > 知识库问答 >
问题:

如何等待setState调用完成时使用useState钩子,立即需要该状态进行API调用?

郦翰学
2023-03-14

我有一个语音听写自定义钩子,还有一个单独的自定义钩子,它将听写结果附加到存储“Note”值的对象。

如果用户过早地单击保存,仍然需要在保存注释的API调用之前追加部分结果。

我的代码如下所示

function NoteDictation(props) {

  const [
    results,
    partialResults,
    error,
    toggleRecognizing,
    speechHasStarted,
  ] = useDictation();

    const [note, setNote, saveNoteAPICall, updateNoteAPICall] = useNote({})
    //Use Note is a custom hook that has that certain type of note's properties built in (they're medical notes, and we have a custom hook for each type of note).



    function handleSavePress(){

      if(partialSpeechResults){
        //If the dictation software hasn't returned a final result, 
        //append the partialSpeechResults
        setNote({...note, text: note.text +  partialSpeechResults})
      }


      //SaveNote does not use the value set above if there are partial results.
      saveNote()
    }

    return (
     <View>
       <NoteContents note={note} results={results} partialResults={partialResults} />
       <Button onPress={handleSavePress> />
    </View>
    )

}

问题是,正在调用SaveNote并且正在使用该注释的旧状态。。。状态设置未按时完成。

我似乎不能在这里使用useEffect钩子来监视更改,因为我正在调用API来立即保存注释,并且在保存时它正在访问注释状态。

处理这件事最好的方法是什么?谢谢你。

共有2个答案

陆畅
2023-03-14

尝试使用效果钩子:

编辑:因为它在第一次渲染时运行,所以在保存之前要确保注释对象不是空的

useEffect(() => {

    if(Object.keys(note).length !== 0){

        saveNote();
    }

});
梁新觉
2023-03-14

根据更新后的代码,您应该能够以与我在原始答案中概述的非常类似的方式处理它:

// will run on mount and whenever note changes
useEffect(() => {
  // skip first run (what you check depends on your initial note value)
  if (Object.keys(note).length) {
    saveNoteAPICall()
  }
}, [note])

function handleSavePress(){
  if(partialSpeechResults){
    // If the dictation software hasn't returned a final result, 
    // append the partialSpeechResults
    // and let if fall into useEffect when note updates
    setNote({...note, text: note.text +  partialSpeechResults})
  } else {
    // run immediately if not partial
    saveNoteAPICall()
  }
}

关键的区别在于,只有在没有部分结果的情况下,才能在press处理程序中调用saveNote。这样你就不会得到不完整的保存。如果您setNote,它将进入useffect并使用正确的值保存。

如果这是处理这些注释的常见模式,那么将此逻辑移到useNotehook中可能是有意义的。

由于您正在使用useState作为注释值,因此您应该能够使用useffect处理此问题。来自useState的值是不可变的,因此它们非常适合作为effects挂钩的输入。将您的呼叫移动到saveNote()把手以外的位置,然后按进入useffect

const [note, setNote] = useState({})

// ...Other misc code

// this will run on first execution,
// and then any time the value of note changes
useEffect(() => {
  // skip first run
  if (Object.keys(note).length) {
    saveNote(note)
  }
}, [note])

function handleSavePress(){
  if (partialSpeechResults) {
    // If the dictation software hasn't returned a final result, 
    // append the partialSpeechResults
    setNote({ ...note, text: note.text +  partialSpeechResults })
  }
}

如果,由于某种原因,您的SaveNote函数是在这个组件中定义的,我建议将它移到组件之外,并将其作为参数传递,这样您就可以确保use效应仅在希望它。如果有一些令人信服的原因,为什么你需要在组件中定义SaveNote,那么你应该用useCallback来定义SaveNote,并改变你的use效应函数来关闭对它的更改:

const [note, setNote] = useState({})

// ...Other misc code

// this function will only change when note changes
const saveNote = useCallback(() => {
  // whatever api call you need to run here
  // that uses the note value in scope
}, [note])

// this will run on first execution,
// and then any time the value of note (and thus saveNote) changes
useEffect(() => {
  // skip first run
  if (Object.keys(note).length) {
    saveNote()
  }
}, [saveNote, note])

function handleSavePress(){
  if (partialSpeechResults) {
    // If the dictation software hasn't returned a final result, 
    // append the partialSpeechResults
    setNote({ ...note, text: note.text +  partialSpeechResults })
  }
}

在没有看到更完整的代码示例的情况下,很难准确地确定可能出现错误的地方。/。。。示例中的其他杂项代码部分很重要,特别是在何处以及如何定义saveNote

 类似资料:
  • 我有一个对象的状态数组: 我有一个添加按钮,用于将对象添加到数组中,这是onclick事件的主体:

  • 我第一次面对的问题很小。我试图使用一个简单的useState,但出于某种原因,我不明白为什么React会给我一个错误,不管我想做什么--没有什么能修复它。 这是错误的图像:错误描述: 错误:无效的钩子调用。钩子只能在函数组件的主体内部调用。这可能是由于以下原因之一:1.React和呈现器(例如React DOM)2的版本可能不匹配。你可能违反了钩子3的规则。在同一个应用程序中可能有多个React副

  • 问题内容: 我分叉了多个流程,我想衡量完成整个任务需要多长时间,即所有分叉的流程都完成了。请告知如何使父进程等待所有子进程终止?我想确保在正确的时间停止计时器。 这是我使用的代码: 问题答案: 我将在“ else // parent”行之后的所有内容都移到for循环之外。在分叉循环之后,使用waitpid进行另一个for循环,然后停止计时并执行其余操作: 我假设如果子进程无法正常退出且状态为0,则

  • 问题内容: React钩子介绍了用于设置组件状态的方法。但是我如何使用钩子来代替如下代码的回调: 我想在状态更新后做一些事情。 我知道我可以用来做其他事情,但是我必须检查状态以前的值,这需要一个位代码。我正在寻找可以与钩子一起使用的简单解决方案。 问题答案: 您需要使用钩子来实现此目的。

  • React hooks引入了来设置组件状态。但是我如何使用钩子来替换回调,如下代码所示:

  • 问题内容: 我有一个循环,可以调用API并将结果编译成数组。我如何等待所有调用完成后才能恢复执行?我看到了一系列有关如何等到打完一个电话的答案,但我不知道如何检查所有这些。如果我做一个while循环,一直等到’obj’是正确的长度,则页面只会停顿直到调用完成,这不是我想要的。请帮助? 问题答案: 如果您使用jQuery的deferred,这很容易。有一种方法,等待多个诺言完成,然后运行回调。那就是