简体   繁体   中英

How to refactor getStaticProps to getServerSideProps in nextjs

In the code below

import Head from 'next/head'
import dynamic from 'next/dynamic'
import { AxiosService } from '../../utils/axios-service'
import styles from './[id].module.scss'
import PostSlider from '../../components/postSlider/postSlider'
import SocialMediaButtons from '../../components/socialMediaButtons/socialMediaButtons'
import { getCloundFrontUrl } from '../../utils/common'

const FroalaEditorView: any = dynamic(() => import('react-froala-wysiwyg/FroalaEditorView'), { ssr: false })

export default function Post({ article, posts }) {
  const title = article[0].title
  const url = article[0].coverImages[0] ? article[0].coverImages[0].url : false
  const alt = article[0].coverImages[0] ? article[0].coverImages[0].alternativeText : ''
  const content = article[0].content
  const date = new Date(article[0].displayDate)
  return (
    <div id='contentsWrap'>
      <Head>
        <title>{title}</title>
        <meta property="og:image" content={url} />
        <meta property="og:title" content={title} />
        <meta property="twitter:image:src" content={url} />
        <meta property="twitter:title" content={title} />
      </Head>
      <div className={styles.imgBanner}>
        {url && <img src={getCloundFrontUrl(url)} alt={alt} />}
        <div>
          <h2>NEWS</h2>
          <h3>{title}</h3>
          <p>{date.getFullYear()}.{date.getMonth() + 1}.{date.getDate()}</p>
        </div>
      </div>
      <div className={`${styles.contentContainer} contentContainer`}>
        <FroalaEditorView model={content} />
      </div>
      <SocialMediaButtons article={article} />
      <PostSlider home={false} posts={posts} />
    </div>
  )
}

export async function getStaticPaths() {
  const axios = AxiosService.create()
  const res = await axios.get('/archives', {
    params: {
      category: 'news',
      display: true,
      showDoson: true,
    }
  })
  const posts = await res.data

  // array of routes possible for [id]
  const paths = posts.map((post) => `/news/${post.id}`)

  // { fallback: false } means routes not inside paths array return 404.
  return { paths, fallback: false }
}

export async function getStaticProps({ params }) {
  const axios = AxiosService.create()
  const resArticle = await axios.get('/archives', {
    params: {
      category: 'news',
      display: true,
      showDoson: true,
      id: params.id,
    }
  })
  const resPosts = await axios.get('/archives', {
    params: {
      category: 'news',
      display: true,
      showDoson: true,
      _limit: 5,
      _sort: 'id:DESC'
    }
  })
  const article = resArticle.data
  return {
    props: {
      article,
      posts: resPosts.data
    },
  }
}

I am using getStaticProps to get data from my strapi cms. Whenever a new article is published on strapi , it should show on my page. Everything works in my localhost because in development (next dev), getStaticProps and getStaticPaths will be called on every request.

However in production, getStaticProps and getStaticPaths is not called at build time whenever strapi creates a new article, so in the code below

  // array of routes possible for [id]
  const paths = posts.map((post) => `/news/${post.id}`)

  // { fallback: false } means routes not inside paths array return 404.
  return { paths, fallback: false }

My latest article id made in strapi cannot be found and results in a 404 error in production.

If I commit and push something, Vercel will deploy my project and call getStaticProps on build time and everything works.

I think the best way to stop seeing this 404 error is to refactor getStaticProps to getServerSideProps because it gets called on every request in both development and production. However I know I cannot use getStaticPaths with getServerSideProps . How would I refactor my code to make everything work?

The answer was surprisingly easy

import Head from 'next/head'
import dynamic from 'next/dynamic'
import { AxiosService } from '../../utils/axios-service'
import styles from './[id].module.scss'
import PostSlider from '../../components/postSlider/postSlider'
import SocialMediaButtons from '../../components/socialMediaButtons/socialMediaButtons'
import { getCloundFrontUrl } from '../../utils/common'

const FroalaEditorView: any = dynamic(() => import('react-froala-wysiwyg/FroalaEditorView'), { ssr: false })

export default function Post({ article, posts }) {
  const title = article[0].title
  // coverImage 없는 경우 페이지 error 발생하지 않고 coverImage 없이 렌더링 함 
  const url = article[0].coverImages[0] ? article[0].coverImages[0].url : false
  const alt = article[0].coverImages[0] ? article[0].coverImages[0].alternativeText : ''
  const content = article[0].content
  const date = new Date(article[0].displayDate)
  return (
    <div id='contentsWrap'>
      <Head>
        <title>{title}</title>
        <meta property="og:image" content={url} />
        <meta property="og:title" content={title} />
        <meta property="twitter:image:src" content={url} />
        <meta property="twitter:title" content={title} />
      </Head>
      <div className={styles.imgBanner}>
        {url && <img src={getCloundFrontUrl(url)} alt={alt} />}
        <div>
          <h2>NEWS</h2>
          <h3>{title}</h3>
          <p>{date.getFullYear()}.{date.getMonth() + 1}.{date.getDate()}</p>
        </div>
      </div>
      <div className={`${styles.contentContainer} contentContainer`}>
        <FroalaEditorView model={content} />
      </div>
      <SocialMediaButtons article={article} />
      <PostSlider home={false} posts={posts} />
    </div>
  )
}

export async function getServerSideProps({ params }) {
  const axios = AxiosService.create()
  const resArticle = await axios.get('/archives', {
    params: {
      category: 'news',
      display: true,
      showDoson: true,
      id: params.id,
    }
  })
  const resPosts = await axios.get('/archives', {
    params: {
      category: 'news',
      display: true,
      showDoson: true,
      _limit: 5,
      _sort: 'id:DESC'
    }
  })
  const article = resArticle.data
  return {
    props: {
      article,
      posts: resPosts.data
    },
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM