代码展示
import React, {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import styles from './index.less';
import { Statistic } from 'antd';
import juxin from '../../../public/img/juxin.png';
import createNum from '../../../public/img/createNum.png';
import cathectic from '../../../public/img/cathectic.png';
import selectNum from '../../../public/img/selectNum.png';
import timekeeping from '/src/public/icon/timekeeping.png';
import { useDispatch } from 'umi';
const { Countdown } = Statistic;
interface cardData {
title: string;
openTime: any;
curTime: any;
tag: string;
explain: string;
id: number | string;
cover: string;
min: string | number;
max: string | number;
num: string | number;
odds: string;
periodsId: string;
issueNo: string;
type: number;
PlayOdds: any;
}
interface cardItemType {
cardList: cardData[];
showCreateModal: (
i: boolean,
t: any,
min: any,
max: any,
num: number | string,
odds: string,
id: number | string,
curTime: string,
) => void;
showCathecticModal: (
i: boolean,
config: {
title: any;
min: any;
max: any;
num: number | string;
odds: string;
id: number | string;
periodsId: string;
},
) => void;
showPourModal: (
i: boolean,
config: {
title: any;
min: any;
max: any;
num: number | string;
odds: string;
id: number | string;
issueNo: any;
timeDiff: any;
type: number;
PlayOdds: any;
},
) => void;
cardConfig: {};
}
export default function CardItem({
cardList,
showCreateModal,
showCathecticModal,
showPourModal,
}: cardItemType) {
const dispatch = useDispatch();
const [isLoad, setIsLoad] = useState(false);
const timeStampsRef = useRef<number[] | null>();
// 在组件挂载时计算所有倒计时的时间戳
useEffect(() => {
const timestamps = cardList.map((item: any) => {
const startTime = new Date(item.cur_time);
const endTime = new Date(item.open_time);
return endTime.getTime() - startTime.getTime() + Date.now();
});
timeStampsRef.current = timestamps;
}, [cardList]);
// 每秒轮询时间戳,检查是否有倒计时结束
useEffect(() => {
const timerId = setInterval(() => {
const now = Date.now();
const finished = timeStampsRef?.current.filter((ts) => ts <= now);
if (finished.length > 0) {
dispatch({
type: 'gameModels/fetchPalyData',
payload: {},
});
setIsLoad(!isLoad);
}
}, 1000);
return () => {
clearInterval(timerId);
};
}, [timeStampsRef, dispatch, isLoad]);
const Cards = ({
title,
tag,
explain,
id,
cover,
min,
max,
num,
odds,
issueNo,
type,
PlayOdds,
curTime,
openTime,
periodsId,
}: cardData) => {
let timeDiff = useMemo(() => {
const timestamps = timeStampsRef.current;
if (!timestamps) {
const startTime = new Date(curTime);
const endTime = new Date(openTime);
return endTime.getTime() - startTime.getTime() + Date.now();
}
const index = cardList.findIndex((item: any) => item.id === id);
if (index >= 0 && index < timestamps.length) {
return timestamps[index];
}
return 0;
}, [id, curTime, openTime, cardList]);
return (
<div className={styles.card} key={id}>
<img className={styles.cover} src={cover} alt="" />
<div className={styles.rightCtx}>
<div className={styles.oneLine}>
<div className={styles.title}>{title}</div>
<div className={styles.countdown}>
<img src={timekeeping} />
<div className={styles.time}>
<Countdown
valueStyle={{ color: '#fff' }}
value={timeDiff}
format="HH:mm:ss"
// onFinish={onFinish}
/>
</div>
</div>
</div>
<div className={styles.tag}>{tag}</div>
<div className={styles.handle}>
<img
src={createNum}
onClick={() =>
showCreateModal(true, title, min, max, num, odds, id, issueNo)
}
></img>
<img
src={cathectic}
onClick={() =>
showCathecticModal(true, {
title,
min,
max,
num,
odds,
id,
periodsId,
})
}
></img>
{/* */}
<img
src={selectNum}
onClick={() =>
showPourModal(true, {
title,
min,
max,
num,
odds,
id,
issueNo,
timeDiff,
type,
PlayOdds,
})
}
></img>
</div>
<div className={styles.explain}>{explain}</div>
</div>
</div>
);
};
return (
<div className={styles.main}>
{cardList.map((item: any, index: number) => {
return (
<Cards
title={item.name}
curTime={item.cur_time}
openTime={item.open_time}
explain={item.remark}
min={item.min}
max={item.max}
num={item.num}
tag={`${item.min}-${item.max}`}
cover={item.cover}
odds={item.odds}
id={item.id}
key={index}
issueNo={item.issue_no}
periodsId={item.periods_id}
type={item.type}
PlayOdds={item.PlayOdds}
/>
);
})}
</div>
);
}
提几个重要的地方 定时器的数据数组要用useRef来保存 这样避免外部变化影响到组件内部更新导致定时器回退