英文:
Countdown is not updating even with SetInterval
问题
我正在尝试创建一个倒计时 Forge 应用,它接受一个日期类型的输入并根据实际日期开始倒计时。例如,我将输入设为“从现在开始的3天后”,但结果只显示为2天23小时59分钟59秒,并且结果不会每秒更新。
以下是主要函数:
const useCountdown = (targetDate) => {
const countDownDate = new Date(targetDate).getTime();
const [countDown, setCountDown] = useState(
countDownDate - new Date().getTime()
);
useEffect(() => {
const interval = setInterval(() => {
setCountDown(countDownDate - new Date().getTime());
}, 1000);
return () => clearInterval(interval);
}, [countDownDate]);
return getReturnValues(countDown);
};
这是显示倒计时的地方:
const Edit = () => {
const THREE_DAYS_IN_MS = 3 * 24 * 60 * 60 * 1000;
const NOW_IN_MS = new Date().getTime();
const dateTimeAfterThreeDays = NOW_IN_MS + THREE_DAYS_IN_MS;
return (
<>
<Text>剩余时间 123:</Text>
<CountdownTimer targetDate={dateTimeAfterThreeDays} />
</>
);
};
export const renderFieldView = render(<View />);
我正在使用 Atlassian Forge 并将应用部署在 Jira 中。
英文:
I am trying to create a countdown forge application that takes an input of type date and starts counting based on the actual date.
As an example, I am giving as input "After 3 days from now", But I only get as a result, 2d:23h:59m:59s , ans this result is not updating every second.
Here is the main function:
const useCountdown = (targetDate) => {
const countDownDate = new Date(targetDate).getTime();
const [countDown, setCountDown] = useState(
countDownDate - new Date().getTime()
);
useEffect(() => {
const interval = setInterval(() => {
setCountDown(countDownDate - new Date().getTime());
}, 1000);
return () => clearInterval(interval);
}, [countDownDate]);
return getReturnValues(countDown);
};
This is where I display the countdown:
const Edit = () => {
const THREE_DAYS_IN_MS = 3 * 24 * 60 * 60 * 1000;
const NOW_IN_MS = new Date().getTime();
const dateTimeAfterThreeDays = NOW_IN_MS + THREE_DAYS_IN_MS;
return(
<Fragment>
<Text>Time left 123:</Text>
<CountdownTimer targetDate={dateTimeAfterThreeDays} />
</Fragment>
)
};
export const renderFieldView = render(<View />);
I am using Atlassian forge and deploying the app in Jira.
答案1
得分: 1
我希望原帖作者现在已经找到了解决方案,但对于任何遇到这个帖子的人,我认为其中一部分原因导致它不起作用是因为它使用了 Atlassian 实现的 useEffect,它的工作方式与 React 不完全相同。
我在这篇博客中更详细地介绍了 Forge 如何在不同种类的应用中使用 hooks:https://blog.developer.atlassian.com/a-deeper-look-at-hooks-in-forge/
我可以确认,如果你使用 UI Kit 2(它使用 React hooks),那么它将会起作用。
英文:
I hope the original poster has found the solution by now, but for anyone coming across this post, I believe part of the reason this isn't working is because it's using UI Kit (original) which uses an Atlassian implementation of useEffect that doesn't work quite the same way as React.
I've written a bit more about how Forge uses hooks in each of the different kinds of apps in this blog https://blog.developer.atlassian.com/a-deeper-look-at-hooks-in-forge/
I can confirm, if you build this using UI Kit 2 (which uses React hooks) then it will work.
答案2
得分: 0
你确定你的控制台没有错误吗?
我唯一能想到的是使用毫秒 (Number
) 作为 Date
,或者反过来。
const { Fragment, useEffect, useState } = React;
const shiftDate = (date) =>
new Date(date.getTime() - date.getTimezoneOffset() * 6e4);
const startOfYearLocal = (date) =>
shiftDate(new Date(date.getFullYear(), 0, 1));
const dayOfYear = (date) =>
Math.floor((date - startOfYearLocal(date)) / 864e5);
const getReturnValues = (dateInMillis) => {
const date = new Date(dateInMillis);
return {
days: dayOfYear(date),
hours: date.getHours(),
minutes: date.getMinutes(),
seconds: date.getSeconds(),
};
};
const useCountdown = (targetDate) => {
const countDownDate = new Date(targetDate).getTime();
const [countDown, setCountDown] = useState(countDownDate - Date.now());
useEffect(() => {
const interval = setInterval(() =>
setCountDown(countDownDate - Date.now()), 1000);
return () => clearInterval(interval);
}, [countDownDate]);
return getReturnValues(countDown);
};
const Text = ({ children }) => <span>{children}</span>;
const CountdownTimer = ({ targetDate }) => {
const { days, hours, minutes, seconds } = useCountdown(new Date(targetDate));
return (
<div className="CountdownTimer">
<span>Days:</span><span>{days}</span>
<span>Hours:</span><span>{hours}</span>
<span>Minutes:</span><span>{minutes}</span>
<span>Seconds:</span><span>{seconds}</span>
</div>
);
};
const Edit = () => {
const THREE_DAYS_IN_MS = 2592e5;
const NOW_IN_MS = Date.now();
const dateTimeAfterThreeDays = NOW_IN_MS + THREE_DAYS_IN_MS;
return (
<Fragment>
<Text>Time Left</Text>
<CountdownTimer targetDate={dateTimeAfterThreeDays} />
</Fragment>
);
};
ReactDOM
.createRoot(document.getElementById('root'))
.render(<Edit />);
html, body, #root {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#root {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.CountdownTimer {
display: grid;
grid-template-columns: repeat(4, auto);
grid-column-gap: 0.5rem;
grid-row-gap: 0.25rem;
padding: 1rem;
}
.CountdownTimer span {
text-align: right;
}
.CountdownTimer span:nth-child(odd) {
font-weight: bold;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
英文:
Are you sure you do not have an error in your console?
The only thing I can think of is using milliseconds (Number
) as a Date
or vice versa.
<!-- begin snippet: js hide: false console: true babel: true -->
<!-- language: lang-js -->
const { Fragment, useEffect, useState } = React;
const shiftDate = (date) =>
new Date(date.getTime() - date.getTimezoneOffset() * 6e4);
const startOfYearLocal = (date) =>
shiftDate(new Date(date.getFullYear(), 0, 1));
const dayOfYear = (date) =>
Math.floor((date - startOfYearLocal(date)) / 864e5);
const getReturnValues = (dateInMillis) => {
const date = new Date(dateInMillis);
return {
days: dayOfYear(date),
hours: date.getHours(),
minutes: date.getMinutes(),
seconds: date.getSeconds(),
};
};
const useCountdown = (targetDate) => {
const countDownDate = new Date(targetDate).getTime();
const [countDown, setCountDown] = useState(countDownDate - Date.now());
useEffect(() => {
const interval = setInterval(() =>
setCountDown(countDownDate - Date.now()), 1000);
return () => clearInterval(interval);
}, [countDownDate]);
return getReturnValues(countDown);
};
const Text = ({ children }) => <span>{children}</span>;
const CountdownTimer = ({ targetDate }) => {
const { days, hours, minutes, seconds } = useCountdown(new Date(targetDate));
return (
<div className="CountdownTimer">
<span>Days:</span><span>{days}</span>
<span>Hours:</span><span>{hours}</span>
<span>Minutes:</span><span>{minutes}</span>
<span>Seconds:</span><span>{seconds}</span>
</div>
);
};
const Edit = () => {
const THREE_DAYS_IN_MS = 2592e5;
const NOW_IN_MS = Date.now();
const dateTimeAfterThreeDays = NOW_IN_MS + THREE_DAYS_IN_MS;
return (
<Fragment>
<Text>Time Left</Text>
<CountdownTimer targetDate={dateTimeAfterThreeDays} />
</Fragment>
);
};
ReactDOM
.createRoot(document.getElementById('root'))
.render(<Edit />);
<!-- language: lang-css -->
html, body, #root {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#root {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.CountdownTimer {
display: grid;
grid-template-columns: repeat(4, auto);
grid-column-gap: 0.5rem;
grid-row-gap: 0.25rem;
padding: 1rem;
}
.CountdownTimer span {
text-align: right;
}
.CountdownTimer span:nth-child(odd) {
font-weight: bold;
}
<!-- language: lang-html -->
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论