如何在 nextjs 中将 getStaticProps 重构为 getServerSideProps

时间:2021-03-18 01:35:09

标签: reactjs next.js strapi

在下面的代码中

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
    },
  }
}

我正在使用 getStaticProps 从我的 strapi cms 获取数据。每当在 strapi 上发表新文章时,它都应该显示在我的页面上。在我的 localhost 中一切正常,因为在开发(下一个开发)中,getStaticPropsgetStaticPaths 将在每个请求中被调用。

但是在生产环境中,getStaticPropsgetStaticPaths 不会在构建时每当 Strapi 创建新文章时调用,因此在下面的代码中

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

无法找到我在 id 发表的最新文章 strapi,并导致生产中出现 404 错误。

如果我提交并推送某些内容,Vercel 将部署我的项目并在构建时调用 getStaticProps,一切正常。

我认为停止看到此 404 错误的最佳方法是将 getStaticProps 重构为 getServerSideProps,因为在开发和生产中的每个请求都会调用它。但是我知道我不能将 getStaticPathsgetServerSideProps 一起使用。我将如何重构我的代码以使一切正常?

1 个答案:

答案 0 :(得分:0)

答案出奇的简单

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
    },
  }
}