我正在将数组传递给组件。我想每秒console.log
数组中的下一项。
在下面的代码中,控制台日志的数量每秒增加一倍:
const Component = ({ someArray }) => {
const [position, setPosition] = React.useState(0);
setInterval(() => {
setPosition(position + 1);
console.log(someArray[position]);
}, 1000);
我认为这是因为组件在position
状态更改时会重新渲染,但是我不确定解决方案是什么。
答案 0 :(得分:0)
防止重复setInterval调用的简单方法(如您所说,在每个渲染器上正确调用):
let clearInterval;
const Component = ({ someArray }) => {
const [position, setPosition] = React.useState(0);
if (!clearInterval) {
clearInterval = setInterval(() => {
setPosition(position + 1);
console.log(someArray[position]);
}, 1000);
}
编辑:
好吧-看来您不能这样调用setPosition。 如果使用标准组件,则容易得多:
class App extends React.Component {
state = { position: 0 };
componentDidMount() {
setInterval(() => {
this.setState({ position: this.state.position + 1 });
}, 1000);
}
render() {
return <button onClick={() => {}}>{this.state.position}</button>;
}
}
答案 1 :(得分:0)
对我来说,从https://reactjs.org/docs/hooks-effect.html来看,您似乎想这样做
useEffect(() => {
setInterval(() => {
setPosition(position + 1);
console.log(someArray[position]);
}, 1000);
}, []);
答案 2 :(得分:0)
由于使用的是React钩子,因此需要结合使用useRef和useEffect-可以在需要时将prevProps与currentProps和clearInterval进行比较。
function usePrevious(value) {
const ref = React.useRef();
React.useEffect(() => {
ref.current = value;
});
return ref.current;
}
const Component = ({ someArray }) => {
const [position, setPosition] = React.useState(0);
const prevArray = usePrevious({ someArray });
React.useEffect(() => {
const timer = setInterval(() => {
setPosition(prevPosition => prevPosition + 1);
}, 1000);
if (prevArray && someArray && prevArray.someArray !== someArray || !someArray[position]) {
clearInterval(timer);
}
return () => clearInterval(timer);
});
return (
<div>Position: {position}</div>
);
}
ReactDOM.render(<Component someArray={['1', '2', '3', '4']} />, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>
让我知道这是否有帮助!
答案 3 :(得分:0)
正如Countingstuff指出的那样,React核心团队对此发表了广泛的博客文章: https://overreacted.io/making-setinterval-declarative-with-react-hooks/
创建一个useInterval挂钩:
import React, { useState, useEffect, useRef } from "react";
function useInterval(callback, delay) {
const savedCallback = useRef();
// Remember the latest callback.
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
// Set up the interval.
useEffect(() => {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () => clearInterval(id);
}
}, [delay]);
}
然后useInterval可以代替setInterval:
const Component = ({ someArray }) => {
const [position, setPosition] = React.useState(0);
setInterval(() => {
useInterval(position + 1);
console.log(someArray[position]);
}, 1000);