【发布时间】:2019-12-12 00:46:07
【问题描述】:
我编写了一个自定义钩子,它维护一个状态并导出该变量并在组件中使用。在钩子内部,变量从不更新,但在组件内部。这是一些简短的代码来演示它。
// useCustomHook.js
export default useCustomHook => {
const [ quesiton, setQuestion ] = useState("")
useEffect(() => {
emitter = new NativeEventEmitter(nativeModule)
emitter.addListener('eventUpdate', e => {
setQuestion(e) // e == "testing"
console.log(question) // question == ""
})
emitter.addListener('eventEnd', e => {
setQuestion(e) // e == "testing"
finishEvent()
})
const finishEvent = () => {
console.log(question) // question == ""
}
}, [])
return [ question ]
}
// component.js
export default component = props => {
const [ question ] = useCustomHook()
return (
<Text>{question}</Text> // question == "testing"
)
}
每次更新事件发生时,组件中的问题都会更新。但在同一个函数中,问题始终是一个空字符串。我无法理解这里发生了什么,这一定是我不理解的 useState setter 的一些奇怪行为。
添加一些说明,至于更新事件中的console.log,我不希望它在该调用中输出正确的值。值永远不会更新的是后续调用。更新函数将被调用 20-30 次,因为在触发结束事件之前将新值发送给它。这可能会在 20-30 秒内发生。被安慰出来的值总是一个空字符串。
【问题讨论】:
-
@EmileBergeron 我会更深入地研究这个,但从表面上看似乎并没有。使用
question的组件显示正确的内容,但调用 setter 的函数显示question的原始状态。所以我调用了setQuestion,组件显示正确的值,但即使后续调用显示不正确的init值 -
setQuestion(e)是异步的,因此它不会立即更改question的值。此外,钩子会记住您传递给它们的大部分内容,因此不会每次都重新创建函数,这意味着question只是函数首次创建时的初始值。如果您想要旧值,请使用 setter 的 updater 函数:setQuestion(oldQuestion => { /* do whatever with it */ return newQuestionValueHere }) -
@EmileBergeron 给了你答案。当
question处于初始空字符串状态时,您的 useEffect 捕获了它,并且您始终记录该值。在 useEffect 回调之外放置一个 console.log 语句,你会看到更少的调用和更好的行为。 -
@EmileBergeron 好的,我知道现在的问题了。它是在 useEffect 中使用的记忆副本。我将函数定义移到了 useEffect 之外,一切都按预期工作。奇怪的是,我很确定我昨天在发布这个问题之前已经这样做了。但我一定有一些不完全一样的事情发生。感谢您的帮助!
标签: javascript reactjs react-native react-hooks