javascriptreactjsnext.jsserver-side-renderingstatic-generator

How To CatchAll in NextJs using getStaticPaths?


I'm trying to use getStaticProps and getStaticPaths to generate pages in build time,

But this is the first time I have dealt with it using CatchAll routes and I tried to search for it but none of the results matched my retirement or what I needed to pass the params id in the URL from getStaticProps to getStaticPaths so I can fetch the Episodes ids from the Info page with the Info page id but looks like I can't do that.

Sorry if my code is a little complex, I tried to make some notes there for more simplicity.

The Code below doesn't work but it froze the watch page when going to it showing what looks like an infinite loop.

Code

/watch/[...params]

export const getStaticPaths = async(props) => {
    // This Code Doesn't Work 
    const {infoId, watchId, gogoInfoId, gogoWatchId} = props
    
    if(infoId){
        // Fetch Info Page And Get Episodes Ids Which Will Be Displayed As Paths
        const req = await axios.get(process.env.API_URL + `/info/${infoId}`)
        const path = req.data?.episodes?.map((items) => {
            return {params: {params: [infoId.toString(), items.id.toString()]}}
        })
        
        return{
            paths: path,
            fallback: false,
        }
    }
    else if(gogoInfoId){
        // Fetch Info Page And Get Episodes Ids Which Will Be Displayed As Paths
        const req = await axios.get(process.env.API_URL_GOGO + `/info/${gogoInfoId}`)
        const path = req.data?.episodes?.map((items) => {
            return {params: {params: [infoId.toString(), items.id.toString()]}}
        })

        return{
            paths: path,
            fallback: false,
        }
    }

} 
export const getStaticProps = async(context) => {
    // Get The Params From The Query In The CatchAll Url
    const {params} = context.query
    const infoId = params[0]
    const watchId = params[1]

    // Main API URLs
    const infoUrl = process.env.API_URL + `/info/${infoId}`
    const watchUrl = process.env.API_URL + `/watch/${watchId}`

    // Backup API
    const infoUrlEnime = process.env.API_URL_GOGO + `/info/${infoId}`
    const watchUrlEnime = process.env.API_URL_GOGO + `/watch/${watchId}`

    try{
        // Checking If Id/params Doesn't Contain Letters 
        if(/^\d+$/.test(infoId)){
            // Fetch From the Main API
            const req1 = await axios.get(infoUrl)
            const req2 = await axios.get(watchUrl)
            return{
                props: {
                    infoData: req1.data,
                    watchData: req2.data,
                    infoId: infoId,
                    watchId: watchId,
                }
            }
        }
        else{
            // Fetch From the Backup API
            const req3 = await axios.get(infoUrlEnime)
            const req4 = await axios.get(watchUrlEnime,{ 
                params: { 
                    server: "vidstreaming"
                } 
            })
            return{
                props: {
                    infoData: req3.data,
                    watchData: req4.data,
                    gogoInfoId: infoId,
                    gogoWatchId: watchId,
                }
            }
        }
    }catch(err){
        // Just A Custom Redirection If Something Went Wrong
        return serversDown(err)
    }
}

Example of what my route looks like http://localhost:3000/watch/142853/tokyo-revengers-seiya-kessen-hen-episode-4

API Schema looks like this:

/info/142853

{
"id": "142853",
...
"episodes": [
  {
   "id": "tokyo-revengers-seiya-kessen-hen-episode-1",
   ...
  },
  {
   "id": "tokyo-revengers-seiya-kessen-hen-episode-2",
   ...
  },
  ...
 ]
}



Solution

  • First, getStaticPaths takes no parameters.

    You can make a call to each of the API addresses and return id and url as params, for each call and put everything together in a paths array.

    Then you can process the data depending on the url and id in getStaticProps.

    Code suggestion:

    export async function getStaticPaths() {
      const resA = await axios.get(process.env.API_URL + `/info/${infoId}`)
      const episodesA = await resA.json()
      const pathsA = episodesA.map(episode => ({
        params: { id: episode.id, url: `${process.env.API_URL}/info/` }
      })
    
      const resB = await axios.get(process.env.API_URL_GOGO + `/info/${infoId}`)
      const episodesB = await resA.json()
      const pathsB = episodesB.map(episode => ({
        params: { id: episode.id, url: `${process.env.API_URL_GOGO}/info/` }
      })
    
      const paths = [ ...pathsA, ...pathsB ]
    
      return{
        paths,
        fallback: false,
      }
    }