我有一个语音听写自定义钩子,还有一个单独的自定义钩子,它将听写结果附加到存储“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(() => {
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()
}
}
关键的区别在于,只有在没有部分结果的情况下,才能在press处理程序中调用saveNote
。这样你就不会得到不完整的保存。如果您setNote
,它将进入useffect
并使用正确的值保存。
如果这是处理这些注释的常见模式,那么将此逻辑移到useNote
hook中可能是有意义的。
由于您正在使用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,这很容易。有一种方法,等待多个诺言完成,然后运行回调。那就是