NextJS 组件
2021-07-26
881
我需要每 30 秒重新加载一次远程 JSON。我目前在 reactJS 中以这种方式执行,但自从转移到 NextJS 后,它就不起作用了
问题是,以下内容在我当前的 ReactJS 网站中运行良好,但一旦我将其移动到 NextJS,它就会到处打印我们的错误。
主要使用以下内容
- fetchTimeout
- sessionStorage
export default function MediaControlCard(props) {
const fetchTimeout = (url, ms, { signal, ...options } = {}) => {
const controller = new AbortController();
const promise = fetch(url, { signal: controller.signal, ...options });
if (signal) signal.addEventListener("abort", () => controller.abort());
const timeout = setTimeout(() => controller.abort(), ms);
return promise.finally(() => clearTimeout(timeout));
};
const controller = new AbortController();
const podcast = props.podcast;
const classes = useStyles();
var token = uuidv4();
// alert(sessionStorage['uuid']);
if(!sessionStorage['uuid']){
sessionStorage.setItem("uuid",token);
}
if(!sessionStorage['station']){
sessionStorage.setItem("station","DRN1");
}
if(!sessionStorage['live']){
sessionStorage.setItem("live",true);
}
var icyStream = "https://api.drn1.com.au:9000/station/"+sessionStorage.station+"?uuid="+sessionStorage['uuid'];
var streamurl = icyStream;//window.com_adswizz_synchro_decorateUrl(icyStream);
React.useEffect(() => {
nowplaying();
document.getElementById("player").muted = false;
});
if(podcast){
alert('test');
}
/*if(!sessionStorage.getItem("station")){
sessionStorage.setItem("station","DRN1");
}*/
function nowplaying(){
// alert("hello");
if(sessionStorage.live === true){
document.getElementById("podcast-only").style.display='none';
}
fetchTimeout(`https://api.drn1.com.au:9000/nowplaying/`+sessionStorage.station+`?uuid=`+sessionStorage['uuid'], 3000, { signal: controller.signal })
.then(res => res.json())
.then(
(result) => {
//console.log("testing player"+result.data);
if(sessionStorage.getItem("live") === 'true'){
switch(result.data[0].track.songtype)
{
case "A":
AdSystem(result.data[0]);
break;
case "S":
Song(result.data[0]);
document.getElementById("Now_Playing_Artist").innerHTML = result.data[0].track.artist;
document.getElementById("Now_Playing_Title").innerHTML = result.data[0].track.title;
document.getElementById("Now_Playing_Cover").style.backgroundImage = "url('"+result.data[0].track.imageurl+"')";
break;
default:
Song(result.data[0]);
document.getElementById("Now_Playing_Artist").innerHTML = result.data[0].track.artist;
document.getElementById("Now_Playing_Title").innerHTML = result.data[0].track.title;
document.getElementById("Now_Playing_Cover").style.backgroundImage = "url('"+result.data[0].track.imageurl+"')";
break;
}
fetch(`https://itunes.apple.com/search?term=${result.data[0].track[0].artist}+${result.data[0].track[0].title}&limit=1`)
.then(res => res.json())
.then(
(result) => {
if(result.results[0]){
document.getElementById("buylink").href = result.results[0].collectionViewUrl;
document.getElementById("buynow").style.display = "block";
}
else
{
document.getElementById("buynow").style.display = "none";
}
})
}
})
.then(console.log)
.catch(error => {
console.error(error);
if (error.name === "AbortError") {
// fetch aborted either due to timeout or due to user clicking the cancel button
} else {
// network error or json parsing error
}
});
setTimeout(function(){nowplaying()}, 10000);
}
return (<>
<Card id="nowplayinginfo_card" className={classes.card}>
<CardMedia
id="Now_Playing_Cover"
className={classes.cover}
image="//tvos.adstichr.com/client/resources/images/stations/Indie/DRN1-Logo.png"
title="Live from space album cover"
/>
<div className={classes.details} id="adstichrNP">
<CardContent className={classes.content} id="song">
<Typography variant="subtitle1">
Now Playing
</Typography>
<Typography id="Now_Playing_Title" component="h6" variant="h6">
{props.artist}
</Typography>
<Typography id="Now_Playing_Artist" variant="subtitle1" color="textSecondary">
{props.song}
</Typography>
</CardContent>
<div id="buynow" className={classes.buynow}>
<a id="buylink" target="_blank" href="#Blank"><img alt="buynow" src="https://linkmaker.itunes.apple.com/assets/shared/badges/en-us/music-lrg-1c05919c6feae5d4731d4399cd656cd72e1fadc4b86d4bd7dc93cb8f3227cb40.svg"/></a>
</div>
<div id="podcast-only" className={classes.controls}>
<audio id="player" className={classes.player} controls controlsList="nodownload" autoPlay muted>
<source src={streamurl}
type="audio/mpeg"
/>
</audio>
</div>
</div>
</Card>
<Card className={classes.card} id="adbanner">
<CardContent className={classes.content} id="adstichr">
</CardContent>
</Card>
</>
)
}
我如何使用 NextJS 实现这一点。我以为我使用 nextjs 放入组件的任何东西都会像 ReactJS 一样工作 - 显然不是。
3个回答
NextJS 具有服务器端渲染功能,您可以放心使用。我认为您应该使用
getStaticProps
,其中有一个名为
revalidate
的特殊属性,它允许您在每次希望使用的超时时发出请求。我从最新的 nextjs(版本 11.0)的官方文档中取了一个例子
文档: https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation
function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li>{post.title}</li>
))}
</ul>
)
}
// This function gets called at build time on server-side.
// It may be called again, on a serverless function, if
// revalidation is enabled and a new request comes in
export async function getStaticProps() {
const res = await fetch('https://.../posts')
const posts = await res.json()
return {
props: {
posts,
},
// Next.js will attempt to re-generate the page:
// - When a request comes in
// - At most once every 10 seconds
revalidate: 10, // In seconds
}
}
export default Blog
Ismoil Shokirov
2021-09-09
您没有显示错误,但我怀疑它与 next.js 的服务器端渲染功能有关。
document
仅在浏览器上定义,并且由于
useEffect
仅在浏览器上执行,因此您在 useEffect 中调用
nowPlaying
。这是正确的。但是
sessionStorage
(无论包是什么)也必须在浏览器上调用。
在组件渲染之前,您应该始终从 useEffect 内的存储中检索数据。
Yilmaz
2021-07-26
是的,您无法使用正确的 NextJS 实现这一点。我正在使用 useSWR 库,它有一些“更新”间隔作为选项。 您可以在 此处 查看。(“选项”部分)
illia chill
2021-07-26