react新特性hooks封装组件清除setInterval定时器
日期:2019-10-30
来源:程序思维浏览:8002次
今天我用hooks封装轮播图组件,发现清除不了setInterval定时器,这个坑如何填?来看看我是怎么解决的吧?
首先先看一下我的组件代码:
import React, {useState, useEffect, useCallback, useRef} from 'react';
import PropTypes from 'prop-types';
import "./style.css";
function Swiper(props){
const [data,setData]=useState([]);
const [isInit,setIsInit]=useState(true);
const [iIndex,setIndex]=useState(0);
//创建一个标识,通用容器
const timer=useRef(null);
//点击切换图片
function changeImg(index){
setIndex(index);
if(data && data.length>0){
for(let i=0;i<data.length;i++){
if(data[i].active){
data[i].active=false;
break;
}
}
data[index].active=true;
//深拷贝解决引用问题
setData(JSON.parse(JSON.stringify(data)));
}
}
//自动播放
const autoPlay=useCallback(()=>{
let tmpIndex=iIndex;
clearInterval(timer.current);
timer.current=setInterval(()=>{
if(data && data.length>0){
for(let i=0;i<data.length;i++){
if(data[i].active){
data[i].active=false;
break;
}
}
if(tmpIndex>=data.length-1){
tmpIndex=0;
}else {
tmpIndex++;
}
setIndex(tmpIndex);
data[tmpIndex].active=true;
setData(JSON.parse(JSON.stringify(data)));
}
},3000)
},[data,iIndex]);
//暂停播放
function stop(){
clearInterval(timer.current);
}
useEffect(()=>{
if(props.data && props.data.length>0 && isInit){
setIsInit(false);
for(let i=0;i<props.data.length;i++){
if(i===0){
props.data[i].active=true;
}else{
props.data[i].active=false;
}
}
setData(props.data);
}
autoPlay();
//页面离开时清除定时器
return ()=>{
clearInterval(timer.current);
}
},[props.data,autoPlay,isInit]);
return(
<div className="my-swiper-main" onMouseOver={stop} onMouseOut={autoPlay}>
{
(data && data.length>0) && data.map((item,index)=>{
return (
<div className={item.active?"slide show":"slide"} key={index}>
<a href={item.url} target="_blank" rel="noopener noreferrer"><img src={item.src} alt=""/></a>
</div>
)
})
}
<div className="pagination">
{
(data && data.length>0) && data.map((item,index)=>{
return (
<div className={item.active?"dot active":"dot"} key={index} onClick={changeImg.bind(this,index)}></div>
)
})
}
</div>
</div>
)
}
export default Swiper;
//检查数据类型
Swiper.propTypes={
data:PropTypes.array.isRequired
};
上面的代码有一个useRef用这个来创建一个标识let timer=useRef(null),里面有一个current将setInterval付给这个变量即可,清除的时候clearInterval(timer.current),这个就可以清除定时器了。
首先先看一下我的组件代码:
import React, {useState, useEffect, useCallback, useRef} from 'react';
import PropTypes from 'prop-types';
import "./style.css";
function Swiper(props){
const [data,setData]=useState([]);
const [isInit,setIsInit]=useState(true);
const [iIndex,setIndex]=useState(0);
//创建一个标识,通用容器
const timer=useRef(null);
//点击切换图片
function changeImg(index){
setIndex(index);
if(data && data.length>0){
for(let i=0;i<data.length;i++){
if(data[i].active){
data[i].active=false;
break;
}
}
data[index].active=true;
//深拷贝解决引用问题
setData(JSON.parse(JSON.stringify(data)));
}
}
//自动播放
const autoPlay=useCallback(()=>{
let tmpIndex=iIndex;
clearInterval(timer.current);
timer.current=setInterval(()=>{
if(data && data.length>0){
for(let i=0;i<data.length;i++){
if(data[i].active){
data[i].active=false;
break;
}
}
if(tmpIndex>=data.length-1){
tmpIndex=0;
}else {
tmpIndex++;
}
setIndex(tmpIndex);
data[tmpIndex].active=true;
setData(JSON.parse(JSON.stringify(data)));
}
},3000)
},[data,iIndex]);
//暂停播放
function stop(){
clearInterval(timer.current);
}
useEffect(()=>{
if(props.data && props.data.length>0 && isInit){
setIsInit(false);
for(let i=0;i<props.data.length;i++){
if(i===0){
props.data[i].active=true;
}else{
props.data[i].active=false;
}
}
setData(props.data);
}
autoPlay();
//页面离开时清除定时器
return ()=>{
clearInterval(timer.current);
}
},[props.data,autoPlay,isInit]);
return(
<div className="my-swiper-main" onMouseOver={stop} onMouseOut={autoPlay}>
{
(data && data.length>0) && data.map((item,index)=>{
return (
<div className={item.active?"slide show":"slide"} key={index}>
<a href={item.url} target="_blank" rel="noopener noreferrer"><img src={item.src} alt=""/></a>
</div>
)
})
}
<div className="pagination">
{
(data && data.length>0) && data.map((item,index)=>{
return (
<div className={item.active?"dot active":"dot"} key={index} onClick={changeImg.bind(this,index)}></div>
)
})
}
</div>
</div>
)
}
export default Swiper;
//检查数据类型
Swiper.propTypes={
data:PropTypes.array.isRequired
};
上面的代码有一个useRef用这个来创建一个标识let timer=useRef(null),里面有一个current将setInterval付给这个变量即可,清除的时候clearInterval(timer.current),这个就可以清除定时器了。
精品好课