开发者问题收集

NextJS 组件

2021-07-26
881

我需要每 30 秒重新加载一次远程 JSON。我目前在 reactJS 中以这种方式执行,但自从转移到 NextJS 后,它就不起作用了

问题是,以下内容在我当前的 ReactJS 网站中运行良好,但一旦我将其移动到 NextJS,它就会到处打印我们的错误。

主要使用以下内容

  1. fetchTimeout
  2. 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