[英]When using useState hook - Is there an importance to changing the setState functions call order?
[英]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
組件里面,那么你應該定義saveNote
與useCallback
和改變你的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.