Russell Harrower
Russell Harrower

Reputation: 845

NextJS component

I need to reload a remote JSON every 30 seconds. I currently do it this way in reactJS but since moving to NextJS it does not work

The issue is that the following work fine in my current ReactJS website but as soon as I Moved it to NextJS it printing our errors everywhere.

Mainly with the following

  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>
    </>
    )
  }

How do I ac achieve this with NextJS. I thought anything I put into component with nextjs would just work the same as ReactJS - clearly not.

Upvotes: 4

Views: 929

Answers (4)

Banedict Fring Drong
Banedict Fring Drong

Reputation: 57

you can use getServerSideProps. Make sure its a page component. getServerSideProps, getStaticProps only works in page component.

    function Page({ data }) {
  // Render data...
}

// This gets called on every request
export async function getServerSideProps() {
  // Fetch data from external API
  const res = await fetch(`https://.../data`)
  const data = await res.json()

  // Pass data to the page via props
  return { props: { data } }
}

export default Page

Upvotes: 0

Ismoil Shokirov
Ismoil Shokirov

Reputation: 3011

NextJS has server-side rendering features for your concern. I believe that you should use getStaticProps there is a special property in it called revalidate it will allow you to make requests on every timeout you wish to use. I took an example from official documentation of latest nextjs(version 11.0)

Docs: 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

Upvotes: 3

illia chill
illia chill

Reputation: 2056

Yes, you can't achieve this with proper NextJS. I am using useSWR library, it has some "update" intervals as an option. You can check it here. ("options" part)

Upvotes: 0

Yilmaz
Yilmaz

Reputation: 49182

You are not showing the errors but I suspect it is related to the server-side rendering feature of next.js.

document is defined only on the browser and since useEffect gets executed only on the browser you are calling nowPlaying inside the useEffect. That is the right thing. However sessionStorage (whatever is the package is) also has to be called on the browser.

You should be always retrieving the data from the storage inside useEffect, before component renders.

Upvotes: 0

Related Questions