Because an article might not be found, Iβve extracted the actual article display into a new component called SingleArticle.
This will make it easier to work with the ternary statement in our ArticlePage component.
Iβve saved this component in a new file at app/components/organisms/SingleArticle.tsx
Eventually (in the next solution step), I will use this component in the single article page.
This component will be responsible for displaying the article title, content, author name, category and images.
import { type JSX } from 'react'
import { FiArrowLeft } from 'react-icons/fi'
import { Link } from 'react-router'
import { toTitleCase } from '#app/utils/stringUtils.js'
import siteLogo from '~/assets/png/epic-news-logo.png'
import { getArticleImgSrc } from '~/utils/misc.js'
interface SingleArticleProps {
export default function SingleArticle ({ article }: SingleArticleProps ) {
const mainImage = article . images [ 0 ]
const imageSrc = mainImage ? getArticleImgSrc ( mainImage . objectKey ) : siteLogo
const categoryTitle = toTitleCase ( article . category ?. name || '' )
const categoryIcons : { [ key : string ]: JSX . Element } = {
Business: < MdOutlineBusinessCenter size = { 20 } className = "text-violet-300" /> ,
Entertainment: < MdOutlineTheaters size = { 20 } className = "text-violet-300" /> ,
Technology: < MdOutlineDesktopMac size = { 20 } className = "text-violet-300" /> ,
< MdOutlineNewspaper size = { 20 } className = "text-violet-300" />
< div className = "container py-16" >
< div className = "lg:w-2/3" >
className = "group text-muted-foreground hover:text-foreground flex items-center gap-2 pb-4 transition"
< FiArrowLeft className = "transition group-hover:-translate-x-1" /> Back
< h2 className = "text-h2 pb-8" > { article . title } </ h2 >
className = { `relative h-[18rem] object-cover md:h-[23rem] lg:h-[28rem]` }
< div className = "absolute inset-0" >
className = "h-full w-full rounded-t-lg object-cover"
< div className = "flex justify-between gap-4 pt-4" >
< div className = "flex items-center gap-2" >
{ categoryIcons [ categoryTitle ] }
< p className = "text-sm text-violet-300" > { categoryTitle } </ p >
< span className = "text-muted-foreground text-sm" >
< div className = "pt-16 text-lg leading-loose whitespace-break-spaces" >
This is a lot of code! But donβt worry, itβs just JSX like we have written before. The logic is simple: weβre displaying the article title, content, author name, category and images.
Take the time to understand how the component works, and how it uses the getArticleImgSrc utility function to get the image source.