以时间间隔反应更新状态

时间:2021-05-13 18:44:23

标签: javascript reactjs react-native

我刚开始研究反应,我有问题 假设我从服务器接收数据,我需要使用一些过滤器将其添加到我的前面。 数据是数组名|年龄 我想以 1 秒的间隔将它添加到前面,所以我需要每 1 秒更新一次我的状态,我尝试了一些变体,但没有任何效果。 那么有人可以帮助我了解如何每 1 秒使用 setState 更新状态吗? 这是我的代码

function App() {
    const people = [
        {name: 'David', age: 24},
        {name: 'James', age: 16},
        {name: 'Angela', age: 29},
        {name: 'Gina', age: 28},
        {name: 'Mike', age: 15},
        {name: 'Laura', age: 30},
        {name: 'Paul', age: 25}
    ]

    const [btnDisabled, setBtnDisabled] = useState(false)
    const [canDrink, setCanDrink] = useState([])

    const interval = function () {
        let i = 0;
        console.log(i)
        const interval = setInterval(() => {
            console.log(i)
            if (people[i]) {
                setBtnDisabled(true)
                if(people[i].age >= 18) {
                    const arr = [...canDrink, people[i]]
                    i++
                    // @ts-ignore
                    setCanDrink(arr)
                }
            } else {
                clearInterval(interval)
                setBtnDisabled(false)
            }
        }, 500)
    }

    return (
        <div className="App">
            <button
                disabled={btnDisabled}
                onClick={() => {
                interval()
            }}>Interval
            </button>
            <ul>{canDrink.map( elem =>
                // @ts-ignore
                <li key={elem.name}>{ elem.name }</li>
            )}
            </ul>
        </div>
    );
}

2 个答案:

答案 0 :(得分:0)

您需要解决两件事。首先,将 i++ 移出 if 块。只有当条件满足时,您才会增加计数器。当它看到有人未成年时,它永远不会增加计数器并无限循环。移动它后,您会注意到您的 canDrink 状态正在发生变化,但很奇怪。那是因为您的区间函数只知道 canDrink 数组的第一个版本(请参阅 closures)。您可以使用 setCanDrink(previousState => [...previousState, people[i]]) 更新您的状态

答案 1 :(得分:0)

您正在寻找的是React.useEffect。您无法在功能组件内有效地执行 setTimout

首先你必须存储一个新的状态变量来记住索引。

const [counter, setCounter] = React.useState(-1);

然后您可以在 React.useEffect 中实现逻辑,当您的 counter 变量更新时,该逻辑将运行。

React.useEffect(() => {
    // This code will run whenever your `counter` variable updates

    // Checking if counter is a valid index
    if (counter >= 0 && people[counter]) {

        // If age of person at `counter` index is < 18, don't do anything, just update counter
        if (people[counter].age < 18) setCounter(counter + 1);

        // If it is a valid user, setTimeout to update canDrink with this user which will update UI after 1 sec
        else {
            setTimeout(() => {
                setCanDrink((canDrink) => [...canDrink, people[counter]]);
                setCounter(counter + 1);
            }, 1000);
        }
     }
}, [counter]);

我为您制作了一个代码沙箱,其中包含一个工作示例。看看吧。

https://codesandbox.io/s/naughty-ardinghelli-sks6z?file=/src/App.js