【问题标题】:useState variable is correct in component but not in custom hook it lives inuseState 变量在组件中是正确的,但在它所在的自定义钩子中不正确
【发布时间】: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 =&gt; { /* do whatever with it */ return newQuestionValueHere })
  • @EmileBergeron 给了你答案。当 question 处于初始空字符串状态时,您的 useEffect 捕获了它,并且您始终记录该值。在 useEffect 回调之外放置一个 console.log 语句,你会看到更少的调用和更好的行为。
  • @EmileBergeron 好的,我知道现在的问题了。它是在 useEffect 中使用的记忆副本。我将函数定义移到了 useEffect 之外,一切都按预期工作。奇怪的是,我很确定我昨天在发布这个问题之前已经这样做了。但我一定有一些不完全一样的事情发生。感谢您的帮助!

标签: javascript reactjs react-native react-hooks


【解决方案1】:

感谢 Emile Bergeron 和 Doug Coburn 为我指明了正确的方向。该值在 useEffect 中被记忆,因此不会在函数中更新。这是我使用示例修复它的方法。

export default useCustomHook => {
    const [ quesiton, setQuestion ] = useState("")
    emitter = new NativeEventEmitter(nativeModule)
    const eventUpdate = e => {
        setQuestion(e) 
        console.log(question) 
    }
    const eventEnd = e => {
        setQuestion(e) 
        finishEvent()
    }
    const finishEvent = () => {
        console.log(question) 
    }
    useEffect(() => {
        emitter.addListener('eventUpdate', eventUpdate)
        emitter.addListener('eventEnd', eventEnd)
    }, [])
    return [ question ]
}

我很确定我已经尝试过了,但我想我之前尝试过的时候还是有问题。我将函数声明放在 useEffect 中,因为我在某处读到这样做更好。因此,如果有人对最佳实践有任何其他建议,我很乐意听到。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-05
    • 2019-04-07
    • 2020-05-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多