Skip to content

Show article images (optional)

We are currently only fetching the id of each image from the database. To display the images on the page, we will need to generate a src for each image using a utility function from the Epic Stack.

If you remember from a previous guide, we created a utility function called getArticleImgSrc to generate a src for each article image.

If you have the getArticleImgSrc function in place, we can now use it to display real article images on the page.

  1. Open app/routes/news.$category.tsx.

    Add the line of code below to pass the id of the first article image to the ArticleCard component:

    app/routes/news.$category.tsx
    24 collapsed lines
    import { invariant } from '@epic-web/invariant'
    import { type LoaderFunctionArgs, json } from '@remix-run/node'
    import { useLoaderData } from '@remix-run/react'
    import ArticleCard from '#app/components/organisms/ArticleCard.tsx'
    import { prisma } from '~/utils/db.server.ts'
    import { toTitleCase } from '~/utils/stringUtils.ts'
    export async function loader({ params }: LoaderFunctionArgs) {
    const { category } = params
    invariant(typeof category === 'string', 'Category not found')
    const categoryTitle = toTitleCase(category)
    const allArticles = await prisma.article.findMany({
    select: {
    id: true,
    title: true,
    category: { select: { name: true } },
    images: { select: { id: true } },
    },
    })
    return json({ categoryTitle, allArticles })
    }
    export default function NewsCategoryPage() {
    const { categoryTitle, allArticles } = useLoaderData<typeof loader>()
    return (
    <div className="container py-16">
    <h2 className="mb-8 text-h2">{categoryTitle}</h2>
    <div className="grid grid-cols-2 gap-6 md:grid-cols-3 lg:grid-cols-5">
    {allArticles.map(article => (
    <ArticleCard
    key={article.id}
    title={article.title}
    category={article.category?.name}
    imageId={article.images[0]?.id}
    />
    ))}
    </div>
    </div>
    )
    }
  2. Open your ArticleCard component.

  3. Add the following import statements at the top of the ArticleCard component file to import the getArticleImgSrc function:

    app/components/organisms/ArticleCard.tsx
    import {
    MdOutlineBusinessCenter,
    MdOutlineTheaters,
    MdOutlineDesktopMac,
    MdOutlineNewspaper,
    } from 'react-icons/md'
    import { getArticleImgSrc } from '~/utils/misc.tsx'
    import siteLogo from '~/assets/svg/site-logo.svg'
    26 collapsed lines
    interface ArticleCardProps {
    title: string
    category?: string
    }
    export default function ArticleCard({
    title,
    category = 'General news',
    }: ArticleCardProps) {
    const categoryIcons: { [key: string]: JSX.Element } = {
    Business: <MdOutlineBusinessCenter size={20} className="text-red-300" />,
    Entertainment: <MdOutlineTheaters size={20} className="text-red-300" />,
    Technology: <MdOutlineDesktopMac size={20} className="text-red-300" />,
    'General news': <MdOutlineNewspaper size={20} className="text-red-300" />,
    }
    return (
    <div className="flex h-64 cursor-pointer flex-col justify-between rounded bg-red-900 p-4 transition-all duration-500 hover:scale-110">
    <h3 className="line-clamp-3 text-xl font-bold">{title}</h3>
    <div className="flex items-center gap-2">
    {categoryIcons[category]}
    <p className="text-sm text-red-300">{category}</p>
    </div>
    </div>
    )
    }
  4. With this in place, let’s now modify the logic inside our ArticleCard component to display the article image above the title:

    app/routes/news.$category.tsx
    8 collapsed lines
    import {
    MdOutlineBusinessCenter,
    MdOutlineTheaters,
    MdOutlineDesktopMac,
    MdOutlineNewspaper,
    } from 'react-icons/md'
    import siteLogo from '~/assets/svg/site-logo.svg'
    import { getArticleImgSrc } from '~/utils/misc.tsx'
    interface ArticleCardProps {
    title: string
    category?: string
    imageId?: string
    }
    export default function ArticleCard({
    title,
    category = 'General news',
    imageId,
    }: ArticleCardProps) {
    const imageSrc = imageId ? getArticleImgSrc(imageId) : siteLogo
    6 collapsed lines
    const categoryIcons: { [key: string]: JSX.Element } = {
    Business: <MdOutlineBusinessCenter size={20} className="text-red-300" />,
    Entertainment: <MdOutlineTheaters size={20} className="text-red-300" />,
    Technology: <MdOutlineDesktopMac size={20} className="text-red-300" />,
    'General news': <MdOutlineNewspaper size={20} className="text-red-300" />,
    }
    return (
    <div>
    <div>
    <img
    src={imageSrc}
    alt={title}
    />
    </div>
    <div className="flex h-64 cursor-pointer flex-col justify-between rounded bg-red-900 p-4 transition-all duration-500 hover:scale-110">
    <h3 className="line-clamp-3 text-xl font-bold">{title}</h3>
    <div className="flex items-center gap-2">
    {categoryIcons[category]}
    <p className="text-sm text-red-300">{category}</p>
    </div>
    </div>
    </div>
    )
    }
  5. Check the browser. You should now see the article images displayed above the title on each article card, although they are not perfect yet:

    Unstyled article card images

In this guide, we learned how to:

  • Pass the id of each article image to the ArticleCard component
  • Use the getArticleImgSrc function to generate the src for each article image
  • Display the article images above the title on each article card
  • Style the article images to make them a consistent size and shape

In the next guide, we will learn how to filter articles by the correct category.