用useState和setInterval反应useEffect

Ada*_*dam 0 reactjs react-hooks

使用以下代码通过组件DOM旋转对象数组。问题是状态永远不会更新,我不能锻炼为什么..?

    import React, { useState, useEffect } from 'react'

const PremiumUpgrade = (props) => {
    const [benefitsActive, setBenefitsActive] = useState(0)


// Benefits Details
const benefits = [
    {
        title: 'Did they read your message?',
        content: 'Get more Control. Find out which users have read your messages!',
        color: '#ECBC0D'
    },
    {
        title: 'See who’s checking you out',
        content: 'Find your admirers. See who is viewing your profile and when they are viewing you',
        color: '#47AF4A'
    }
]


// Rotate Benefit Details
useEffect(() => {
    setInterval(() => {
        console.log(benefits.length)
        console.log(benefitsActive)

        if (benefitsActive >= benefits.length) {
            console.log('................................. reset')
            setBenefitsActive(0)
        } else {
            console.log('................................. increment')
            setBenefitsActive(benefitsActive + 1)
        }
    }, 3000)
}, [])
Run Code Online (Sandbox Code Playgroud)

我得到的输出如下图所示。我可以看到useState'setBenefitsActive'被调用,但'benefitsActive'从未更新。

在此处输入图片说明

Deh*_*oos 7

一些代码为您的利益!在 @James 建议的 useEffect 中,向正在更新的变量添加依赖项。另外不要忘记清理你的间隔以避免内存泄漏!

// Rotate Benefit Details
useEffect(() => {
    let rotationInterval = setInterval(() => {
        console.log(benefits.length)
        console.log(benefitsActive)

        if (benefitsActive >= benefits.length) {
            console.log('................................. reset')
            setBenefitsActive(0)
        } else {
            console.log('................................. increment')
            setBenefitsActive(benefitsActive + 1)
        }
    }, 3000)
    
    //Clean up can be done like this
    return () => {
        clearInterval(rotationInterval);
    }
}, [benefitsActive]) // Add dependencies here 
Run Code Online (Sandbox Code Playgroud)

工作沙箱:https : //codesandbox.io/s/react-hooks-interval-demo-p1f2n

编辑

正如 James 所指出的,这可以通过 setTimeout 以更清晰的实现更好地实现。

// Rotate Benefit Details
useEffect(() => {
    let rotationInterval = setTimeout(() => {
        console.log(benefits.length)
        console.log(benefitsActive)

        if (benefitsActive >= benefits.length) {
            console.log('................................. reset')
            setBenefitsActive(0)
        } else {
            console.log('................................. increment')
            setBenefitsActive(benefitsActive + 1)
        }
    }, 3000)
    

}, [benefitsActive]) // Add dependencies here 
Run Code Online (Sandbox Code Playgroud)

在这里,由于在每次 setTimeout 之后调用 useEffect 会自动创建一种间隔,从而创建一个闭环。

如果你仍然想使用间隔,尽管清理是强制性的,以避免内存泄漏。


Jam*_*mes 6

您没有传递任何依赖关系来useEffect表示它只会运行一次,结果for的参数setInterval将永远只接收的初始值benefitsActive(在这种情况下为0)。

您可以使用函数而不是仅通过设置值来修改现有状态,即

setBenefitsActive(v => v + 1);
Run Code Online (Sandbox Code Playgroud)