我正在嘗試在 Next.js 中進行頁面轉換。由于過渡比頁面加載慢,我需要計算影片完成的缺失時間。過渡應至少持續 2 秒,1 秒用于加載螢屏的淡入,500 毫秒以使加載螢屏保持一點,500 毫秒用于退出。
我實際上正在嘗試使用new Date.getTime()并獲取自影片開始以來經過的時間量來實作這一點。
我嘗試使用以下代碼來檢查代碼是否正確:
function testDateValues() {
var startTime = new Date().getTime();
var animDuration = 1500; // In milliseconds
setTimeout(() => {
console.log(animDuration - (new Date().getTime() - startTime));
}, 1000);
}
此函式列印 1 秒后丟失的時間,即 500 毫秒(列印 498-502 之間的數字,但它是正確的)。
但是,當我將此代碼轉換為 Next.js 時,我得到的數字類似于-19604、-60418和與剩余影片時間無關的數字。
代碼如下(簡化):
import { useRouter } from 'next/router';
import { useState } from 'react';
export default function LoadingScreen() {
const router = useRouter();
const [loading, setLoading] = useState(false);
const [loadingStartTime, setLoadingStartTime] = useState(new Date().getTime());
useEffect(() => {
const handleStart = () => {
console.log("Loading started");
setLoading(true);
setLoadingStartTime(new Date().getTime());
};
const handleComplete = () => {
console.log("Loading completed");
console.log(1500 - (new Date().getTime() - loadingStartTime));
setTimeout(() => {
setLoading(false);
}, 1500 - (new Date().getTime() - loadingStartTime));
};
router.events.on("routeChangeStart", handleStart);
router.events.on("routeChangeComplete", handleComplete);
router.events.on("routeChangeError", handleComplete);
return () => {
router.events.off("routeChangeStart", handleStart);
router.events.off("routeChangeComplete", handleComplete);
router.events.off("routeChangeError", handleComplete);
};
}, []);
return {loading && (<div>Loading</div>)}
}
該加載螢屏在components/layout.jsx檔案中。
import LoadingScreen from "./LoadingScreen";
export default function Layout({ children }) {
return (
<>
<motion.main>{children}</motion.main>
<LoadingScreen />
</>
)
}
加載螢屏甚至沒有顯示一段時間。沒有頁面轉換。
為什么幾乎相同的代碼回傳如此不同的值?(為什么 -19604 而不是 500?)
uj5u.com熱心網友回復:
您的問題是loadingStartTime組件加載時已初始化,并且該常量值是效果中的代碼將使用的值。該setLoadingStartTime呼叫對關閉的constvalue沒有影響,它所做的只是導致組件重新渲染。但是,這不會導致效果再次運行。
有多種方法可以解決這個問題:
不要使用狀態,
loadingStartTime而只是在效果處理程式范圍內使用可變變數:export default function LoadingScreen() { const router = useRouter(); const [loading, setLoading] = useState(false); useEffect(() => { let loadingStartTime = Date.now(); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ const handleStart = () => { console.log("Loading started"); setLoading(true); loadingStartTime = Date.now(); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ }; const handleComplete = () => { console.log("Loading completed"); console.log(1500 - (Date.now() - loadingStartTime)); setTimeout(() => { setLoading(false); }, 1500 - (Date.now() - loadingStartTime)); }; router.events.on("routeChangeStart", handleStart); router.events.on("routeChangeComplete", handleComplete); router.events.on("routeChangeError", handleComplete); return () => { router.events.off("routeChangeStart", handleStart); router.events.off("routeChangeComplete", handleComplete); router.events.off("routeChangeError", handleComplete); }; }, []); return {loading && (<div>Loading</div>)} }不要使用狀態,
loadingStartTime而是在轉換開始時初始化的常量:export default function LoadingScreen() { const router = useRouter(); const [loading, setLoading] = useState(false); useEffect(() => { const handleStart = () => { console.log("Loading started"); setLoading(true); const loadingStartTime = Date.now(); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ const handleComplete = () => { console.log("Loading completed"); console.log(1500 - (Date.now() - loadingStartTime)); setTimeout(() => { setLoading(false); }, 1500 - (Date.now() - loadingStartTime)); }; router.events.once("routeChangeComplete", handleComplete); router.events.once("routeChangeError", handleComplete); }; router.events.on("routeChangeStart", handleStart); return () => { router.events.off("routeChangeStart", handleStart); }; }, []); return {loading && (<div>Loading</div>)} }請注意,即使在組件已卸載后,這仍將保留完整的錯誤處理程式,這可能是可取的,也可能不是可取的 - 或者根本不重要。
使用兩個具有適當依賴關系的單獨效果:
export default function LoadingScreen() { const router = useRouter(); const [loading, setLoading] = useState(false); const [loadingStartTime, setLoadingStartTime] = useState(Date.now()); useEffect(() => { const handleStart = () => { console.log("Loading started"); setLoading(true); setLoadingStartTime(Date.now()); }; router.events.on("routeChangeStart", handleStart); return () => { router.events.off("routeChangeStart", handleStart); }; }, []); useEffect(() => { // ^^^^^^^^^ console.log("New loadingStartTime", Date(loadingStartTime)); const handleComplete = () => { console.log("Loading completed"); console.log(1500 - (Date.now() - loadingStartTime)); setTimeout(() => { setLoading(false); }, 1500 - (Date.now() - loadingStartTime)); }; router.events.on("routeChangeComplete", handleComplete); router.events.on("routeChangeError", handleComplete); return () => { router.events.off("routeChangeComplete", handleComplete); router.events.off("routeChangeError", handleComplete); }; }, [loadingStartTime]); // ^^^^^^^^^^^^^^^^ return {loading && (<div>Loading</div>)} }
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/522218.html
下一篇:帶有ajax、jquery、post的剃須刀頁面。dataTablesUncaughtTypeError:無法設定空屬性(設定“資料”)
