簡體   English   中英

在使用立即需要該狀態的useState掛鈎進行API調用時,如何等待setState調用結束?

[英]How to await a setState call finishing when using useState hook that immediately needs that state to make an API call?

我有一個語音聽寫自定義鈎子,以及一個單獨的自定義鈎子,它將聽寫結果附加到存儲“注釋”值的對象。

如果用戶過早點擊保存,則仍然需要在保存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來立即保存注釋並且在保存時它正在訪問注釋狀態。

處理這個問題的最佳方法是什么? 謝謝。

試試useEffect鈎子:

編輯:由於它在第一次渲染時運行,因此您希望在保存之前確保注釋對象不為空

useEffect(() => {

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

        saveNote();
    }

});

編輯

鑒於更新的代碼,您應該能夠像我在原始答案中概述的那樣處理它:

// 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在您的印刷機處理程序中調用saveNote 這樣你就不會得到不完整的保存。 如果你setNote ,它將進入你的useEffect並使用正確的值保存。

如果這是處理這些注釋的常用模式,則將此邏輯移動到useNote鈎子中可能是有意義的。


原始答案

由於您使用useState作為note值,因此您應該能夠使用useEffect來處理它。 useState中的值是不可變的,因此它們非常適合作為效果掛鈎的輸入。 將您的調用移到saveNote()之外的handleSavePress saveNote()並進入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組件里面,那么你應該定義saveNoteuseCallback和改變你的useEffect功能鍵關機的變化是:

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示例中的// ...Other misc code部分非常重要,特別是在定義saveNote位置和方式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM