我不明白为什么当我使用setTimeout函数时,我的react组件开始到infinite console.log。一切都在工作,但PC开始滞后的地狱。
有人说这个函数在超时时改变我的状态还有那个重新渲染组件,设置新定时器等等。现在我需要知道如何证明它是正确的。
export default function Loading() {
// if data fetching is slow, after 1 sec i will show some loading animation
const [showLoading, setShowLoading] = useState(true)
let timer1 = setTimeout(() => setShowLoading(true), 1000)
console.log('this message will render every second')
return 1
}
明确在不同版本的代码中没有帮助:
const [showLoading, setShowLoading] = useState(true)
let timer1 = setTimeout(() => setShowLoading(true), 1000)
useEffect(
() => {
return () => {
clearTimeout(timer1)
}
},
[showLoading]
)
如果你想创建一个类似“start”的按钮,那么使用“useInterval”钩子可能不合适,因为react不允许你调用组件顶部以外的钩子。
export default function Loading() {
// if data fetching is slow, after 1 sec i will show some loading animation
const [showLoading, setShowLoading] = useState(true)
const interval = useRef();
useEffect(() => {
interval.current = () => setShowLoading(true);
}, [showLoading]);
// make a function like "Start"
// const start = setInterval(interval.current(), 1000)
setInterval(() => interval.current(), 1000);
console.log('this message will render every second')
return 1
}
每10秒触发一次api:
useEffect(() => {
const timer = window.setInterval(() => {
// function of api call
}, 1000);
return () => {
window.clearInterval(timer);
}
}, [])
如有状态变化:
useEffect(() => {
// add condition to state if needed
const timer = window.setInterval(() => {
// function of api call
}, 1000);
return () => {
window.clearInterval(timer);
}
}, [state])
如果在其他人给出的例子中使用useEffect钩子来避免连续地将setInterval方法附加(挂载)和分离(卸载)到事件循环,您可能会转而使用useReducer。
想象这样一个场景:给定的秒和分,你要开始倒数……
下面我们得到了一个减速器函数,它执行倒计时逻辑。
const reducer = (state, action) => {
switch (action.type) {
case "cycle":
if (state.seconds > 0) {
return { ...state, seconds: state.seconds - 1 };
}
if (state.minutes > 0) {
return { ...state, minutes: state.minutes - 1, seconds: 60 };
}
case "newState":
return action.payload;
default:
throw new Error();
}
}
现在我们要做的就是在每个间隔中分派循环动作:
const [time, dispatch] = useReducer(reducer, { minutes: 0, seconds: 0 });
const { minutes, seconds } = time;
const interval = useRef(null);
//Notice the [] provided, we are setting the interval only once (during mount) here.
useEffect(() => {
interval.current = setInterval(() => {
dispatch({ type: "cycle" });
}, 1000);
// Just in case, clear interval on component un-mount, to be safe.
return () => clearInterval(interval.current);
}, []);
//Now as soon as the time in given two states is zero, remove the interval.
useEffect(() => {
if (!minutes && !seconds) {
clearInterval(interval.current);
}
}, [minutes, seconds]);
// We could have avoided the above state check too, providing the `clearInterval()`
// inside our reducer function, but that would delay it until the next interval.
如果你想创建一个类似“start”的按钮,那么使用“useInterval”钩子可能不合适,因为react不允许你调用组件顶部以外的钩子。
export default function Loading() {
// if data fetching is slow, after 1 sec i will show some loading animation
const [showLoading, setShowLoading] = useState(true)
const interval = useRef();
useEffect(() => {
interval.current = () => setShowLoading(true);
}, [showLoading]);
// make a function like "Start"
// const start = setInterval(interval.current(), 1000)
setInterval(() => interval.current(), 1000);
console.log('this message will render every second')
return 1
}