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

标签 javascript reactjs react-hooks

我有一个语音听写自定义 Hook ,以及一个单独的自定义 Hook ,该 Hook 将听写结果附加到存储“音符”值的对象。

如果用户过早点击保存,我仍然需要在保存注释的 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 Hook 来监视更改,因为我正在调用 API 以立即保存笔记,并且它在保存时访问笔记状态。

处理此问题的最佳方法是什么?谢谢。

最佳答案

编辑

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

// 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()
  }
}

主要区别在于,如果您没有部分结果,您只能在新闻处理程序中调用 saveNote。这样你就不会得到不完整的保存。如果您 setNote,它将放入您的 useEffect 并以正确的值保存。

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


原始答案

因为您正在为您的 note 值使用 useState,所以您应该能够使用 useEffect 来处理它。 useState 中的值是不可变的,因此它们非常适合用作效果 Hook 的输入。将对 saveNote() 的调用从 handleSavePress 移到 useEffect 中:

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 函数是在该组件内定义的,我建议将其移至组件外部并将其作为参数传递给 note,这样您就可以确保 useEffect 仅在您需要时运行。如果有一些令人信服的理由需要在组件内部定义 saveNote,那么您应该使用 useCallback 定义 saveNote 并更改您的 使用 Effect 函数来关闭对其的更改:

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 })
  }
}

在没有看到更完整的代码示例的情况下,很难准确地确定哪里出了问题。您的示例的 //...Other misc code 部分很重要,尤其是您定义 saveNote 的位置和方式。

关于javascript - 使用立即需要该状态进行 API 调用的 useState Hook 时,如何等待 setState 调用完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57138642/

相关文章:

javascript - React 函数高阶组件

javascript - React async wait 函数按执行顺序阻止 useDispatch

javascript - 如何满足网站上的 HTTP 和 HTTPS 请求?

javascript - 如何获取使用 Windows-1251 的文件的 base 64 编码

javascript - Google Storage API - 可恢复上传、AJAX、CORS 错误

reactjs - 如何在我的 PostgreSQL 日期时间中避免 "Z"

reactjs - 默认禁用按钮单击事件不会在 reactjs 上触发

javascript - settimeout while audio.duration

javascript - Material-ui 工具提示无法正常工作

reactjs - 使用 typescript : Property 'data' does not exist on type react 钩子(Hook)