如何使用 React Native 正确清除间隔
How to clearInterval correctly using React Native
在 RN 中,我有一个使用 setInterval 的倒数计时器,从 10 到 0。
一旦满足时间 === 0 或小于 1 的条件,我希望间隔停止。
倒计时正在工作但不断重复,clearInterval 不起作用。
我做错了什么?
import { StyleSheet, Text } from 'react-native'
import React, {useEffect, useState} from 'react'
export default function Timer() {
const [time, setTime] = useState(10)
useEffect(() => {
if(time > 0) {
var intervalID = setInterval(() => {
setTime(time => time > 0 ? time - 1 : time = 10)
}, 1000)
} else {
clearInterval(intervalID)
}
}, [])
return <Text style={styles.timer}>{time}</Text>
}
函数在 useEffect 上,仅在组件为 mounted/unmounted 时执行,在函数执行的那一刻,时间为 10,因此永远不会进入 else 条件。
此代码一定适合您:
import { StyleSheet, Text } from 'react-native'
import React, {useEffect, useState} from 'react'
export default function Timer() {
const [time, setTime] = useState(10)
time <= 0 && clearInterval(intervalID)
useEffect(() => {
var intervalID = setInterval(() => {
setTime(time => time > 0 ? time - 1 : time = 10)
}, 1000)
return () => {
clearInterval(intervalID)
}
}, [])
return <Text style={styles.timer}>{time}</Text>
ClearInterval应该在setTime里面,因为useEffect只会触发一次
注意:您还应该在卸载时清除。
export default function Timer() {
const [time, setTime] = useState(10);
useEffect(() => {
var intervalID = setInterval(() => {
setTime((time) => {
if (time > 0) {
return time - 1;
}
clearInterval(intervalID);
return time;
});
}, 1000);
return () => clearInterval(intervalID);
}, []);
return <Text style={styles.timer}>{time}</Text>;
}
你也可以使用这个:
import React, { useEffect, useState, useRef } from 'react'
import { Text } from 'react-native'
const Timer = () => {
const [time, setTime] = useState(10)
const promiseRef = useRef(null)
useEffect(() => {
if(time > 0) {
promiseRef.current = setInterval(() => {
setTime(time => time > 0 ? time - 1 : time = 10)
}, 1000)
} else {
promiseRef.current = null
}
}, [])
return <Text style={styles.timer}>{time}</Text>
}
export default Timer
您的 useEffect 在依赖项数组中没有任何值(时间),因此它 运行 只会在组件挂载时出现一次。
const [time, setTime] = useState(10);
useEffect(() => {
if (time === 0) {
return;
}
const timeoutId = setInterval(() => {
setTime(time - 1);
}, 1000);
return () => {
clearInterval(timeoutId);
};
}, [time]);
您也可以使用超时,在这种情况下您不需要清除任何内容,因为它 运行 每个 useEffect 触发器只会执行一次。
useEffect(() => {
if (time === 0) {
return;
}
setTimeout(() => {
setTime(time - 1);
}, 1000);
}, [time]);
如果您不想将 time
添加到依赖项数组,另一个可能有效的选项是清除 setTime
中的间隔
useEffect(() => {
const intervalID = setInterval(() => {
setTime((time) => {
if (time === 0) {
clearInterval(intervalID);
return time;
}
return time - 1;
});
}, 1000);
return () => {
clearInterval(intervalID);
};
}, []);
请注意,在您的示例中,您正在倒数到 1,然后倒数到 10,因此它永远不会达到 0
setTime(time => time > 0 ? time - 1 : time = 10)
如果你希望它在完成计数后重置回 10,最后一个选项可能适合你,因为它不会在每次更改时触发效果,只需要 return 10
而不是 time
清除间隔后
这是一个例子https://jsfiddle.net/dnyrm68t/
在 RN 中,我有一个使用 setInterval 的倒数计时器,从 10 到 0。 一旦满足时间 === 0 或小于 1 的条件,我希望间隔停止。 倒计时正在工作但不断重复,clearInterval 不起作用。 我做错了什么?
import { StyleSheet, Text } from 'react-native'
import React, {useEffect, useState} from 'react'
export default function Timer() {
const [time, setTime] = useState(10)
useEffect(() => {
if(time > 0) {
var intervalID = setInterval(() => {
setTime(time => time > 0 ? time - 1 : time = 10)
}, 1000)
} else {
clearInterval(intervalID)
}
}, [])
return <Text style={styles.timer}>{time}</Text>
}
函数在 useEffect 上,仅在组件为 mounted/unmounted 时执行,在函数执行的那一刻,时间为 10,因此永远不会进入 else 条件。
此代码一定适合您:
import { StyleSheet, Text } from 'react-native'
import React, {useEffect, useState} from 'react'
export default function Timer() {
const [time, setTime] = useState(10)
time <= 0 && clearInterval(intervalID)
useEffect(() => {
var intervalID = setInterval(() => {
setTime(time => time > 0 ? time - 1 : time = 10)
}, 1000)
return () => {
clearInterval(intervalID)
}
}, [])
return <Text style={styles.timer}>{time}</Text>
ClearInterval应该在setTime里面,因为useEffect只会触发一次
注意:您还应该在卸载时清除。
export default function Timer() {
const [time, setTime] = useState(10);
useEffect(() => {
var intervalID = setInterval(() => {
setTime((time) => {
if (time > 0) {
return time - 1;
}
clearInterval(intervalID);
return time;
});
}, 1000);
return () => clearInterval(intervalID);
}, []);
return <Text style={styles.timer}>{time}</Text>;
}
你也可以使用这个:
import React, { useEffect, useState, useRef } from 'react'
import { Text } from 'react-native'
const Timer = () => {
const [time, setTime] = useState(10)
const promiseRef = useRef(null)
useEffect(() => {
if(time > 0) {
promiseRef.current = setInterval(() => {
setTime(time => time > 0 ? time - 1 : time = 10)
}, 1000)
} else {
promiseRef.current = null
}
}, [])
return <Text style={styles.timer}>{time}</Text>
}
export default Timer
您的 useEffect 在依赖项数组中没有任何值(时间),因此它 运行 只会在组件挂载时出现一次。
const [time, setTime] = useState(10);
useEffect(() => {
if (time === 0) {
return;
}
const timeoutId = setInterval(() => {
setTime(time - 1);
}, 1000);
return () => {
clearInterval(timeoutId);
};
}, [time]);
您也可以使用超时,在这种情况下您不需要清除任何内容,因为它 运行 每个 useEffect 触发器只会执行一次。
useEffect(() => {
if (time === 0) {
return;
}
setTimeout(() => {
setTime(time - 1);
}, 1000);
}, [time]);
如果您不想将 time
添加到依赖项数组,另一个可能有效的选项是清除 setTime
useEffect(() => {
const intervalID = setInterval(() => {
setTime((time) => {
if (time === 0) {
clearInterval(intervalID);
return time;
}
return time - 1;
});
}, 1000);
return () => {
clearInterval(intervalID);
};
}, []);
请注意,在您的示例中,您正在倒数到 1,然后倒数到 10,因此它永远不会达到 0
setTime(time => time > 0 ? time - 1 : time = 10)
如果你希望它在完成计数后重置回 10,最后一个选项可能适合你,因为它不会在每次更改时触发效果,只需要 return 10
而不是 time
清除间隔后
这是一个例子https://jsfiddle.net/dnyrm68t/