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