reactjs - 空投智能合约组件时间不倒计时?
问题描述
我有空投组件,如果在几秒钟后存入一定数量的硬币,我想在其中空投硬币。所以如果存了金额,我想倒计时,然后给用户一些硬币。但是倒计时功能不起作用。组件重新渲染,但时间仅从 20 变为 19,然后停止。
这个组件只需要 2 个道具。
<Airdrop
stakingBalance="50000000000000000000"
// this can be ignored. it wont break the app
// decentralBankContract={props.decentralBankContract}
/>
我手动通过 stakingBalance="50000000000000000000" 来测试组件。这是组件本身,您可以将组件复制到您的项目中,或者这里是 repo 的 github 地址:https ://github.com/yilmazbingo/erc20-token
const Airdrop = (props) => {
console.log("props in Airdrop", props);
const [timeState, setTimeState] = useState({ time: {}, seconds: 20 });
const [timer, setTimer] = useState(0);
useEffect(() => {
let timeLeftVar = secondsToTime(timeState.seconds);
console.log("timelfetvar", timeLeftVar);
setTimeState((prevState) => ({ ...prevState, ...timeLeftVar }));
}, []);
const startTimer = () => {
if (timer == 0 && timeState.seconds > 0) {
setTimer(setInterval(countDown, 1000));
console.log("timer state", timer);
}
};
const countDown = () => {
// 1 . countdown one second at a time
let seconds = timeState.seconds - 1;
setTimeState((prevState) => ({
...prevState,
time: secondsToTime(seconds),
seconds: seconds - 1,
}));
// 2. stop counting when we hit zero
if (timeState.seconds == 0) {
clearInterval(timer);
}
};
const secondsToTime = (secs) => {
let hours, minutes, seconds;
hours = Math.floor(secs / (60 * 60));
let divisor_for_minutes = secs % (60 * 60);
minutes = Math.floor(divisor_for_minutes / 60);
let divisor_for_seconds = divisor_for_minutes % 60;
seconds = Math.ceil(divisor_for_seconds);
let obj = {
h: hours,
m: minutes,
s: seconds,
};
return obj;
};
const airdropReleaseTokens = () => {
let stakingB = props.stakingBalance;
if (stakingB >= "50000000000000000000") {
startTimer();
}
};
airdropReleaseTokens();
return (
<div style={{ color: "black" }}>
{timeState.time.m}:{timeState.time.s}
</div>
);
};
export default Airdrop;
组件重新渲染,我相信这个问题与 countdown() 有关。我把它改成这样:
const countDown = () => {
setTimeState((prevState) => ({
...prevState,
time: secondsToTime(timeState.seconds),
seconds: prevState.seconds - 1,
}));
// 2. stop counting when we hit zero
if (timeState.seconds == 0) {
clearInterval(timer);
}
};
这也不起作用。
解决方案
const [timeState, setTimeState] = useState({ time: {}, seconds: 20 });
像这样设置状态是个坏主意。我将秒分隔为“airdropTime”,以便我可以将其作为依赖项添加到 useEffect()。
const Airdrop = (props) => {
console.log("props in Airdrop", props);
const [timeState, setTimeState] = useState({ time: {} });
const [airdropTime, setAirdropTime] = useState(10);
const [timer, setTimer] = useState(0);
useEffect(() => {
let timeLeftVar = secondsToTime(airdropTime);
console.log("timelfetvar", timeLeftVar);
setTimeState((prevState) => ({ ...prevState, time: timeLeftVar }));
if (airdropTime === 0) {
console.log("airdrip time iszero");
clearInterval(timer);
}
}, [airdropTime]);
// this will start the timer
const airdropReleaseTokens = () => {
let stakingB = props.stakingBalance;
if (stakingB >= "50000000000000000000") {
startTimer();
}
};
// each secon state count down will be called and state will be updated
const startTimer = () => {
if (timer === 0 && airdropTime > 0) {
setTimer(setInterval(countDown, 1000));
}
};
const countDown = () => {
setTimeState((prevState) => ({
...prevState,
time: secondsToTime(airdropTime),
}));
setAirdropTime((prevState) => prevState - 1);
};
const secondsToTime = (secs) => {
let hours, minutes, seconds;
hours = Math.floor(secs / (60 * 60));
let divisor_for_minutes = secs % (60 * 60);
minutes = Math.floor(divisor_for_minutes / 60);
let divisor_for_seconds = divisor_for_minutes % 60;
seconds = Math.ceil(divisor_for_seconds);
let obj = {
h: hours,
m: minutes,
s: seconds,
};
return obj;
};
airdropReleaseTokens();
return (
<div style={{ color: "black" }}>
{timeState.time.m}:{timeState.time.s}
</div>
);
};
推荐阅读
- typescript - 对象内函数中的泛型
- redmine - 如何在屏幕上轻松查看 redmine 的所有内容,例如项目和票证?
- android - Xamarin Android TapGestureRecognizer 未触发
- javascript - 使用 VS 代码使用带有凉亭的 d3-context-menu 安装时遇到问题
- c# - 通过陀螺仪输入时如何垂直制作二维刚体
- java - Java Swing JButton对齐 - BoxLayout
- python - 如何存储函数输出而不在 Spyder 中重新运行函数
- kivy - 不显示没有扩展名的 jpg 图像
- python - 猪拉丁编码
- linux - 如何在 docker 文件中包含 shell 脚本套件