FeTodeschini / vegan-mundi

Code for the Vegan Mundi eCommerce platform for selling online and in-person vegan cooking classes. Stack: NextJs, Typescript NodeJs, MySQL (AWS RDS) and images and videos stored in AWS S3 private buckets. Client and server apps hosted on AWS EC2, with a Jenkins CI/CD running in Docker containers in an AWS EC2 instance.
1 stars 0 forks source link

Convert Gallery component to Server Side Rendering (SSR) #21

Closed FeTodeschini closed 2 weeks ago

FeTodeschini commented 2 months ago

Convert classes\[category]\page.tsx from CSR (client side rendering) to SSR (Server Side Rendering).

This is the page that displays all classes for a specific category determined by the dynamic route.

FeTodeschini commented 2 weeks ago

classes\[category]\page.tsx was converted to SSR, but it was rolled back, as after the purchase of a class, it would still be displayed in classes\[category]\page.tsx when the image for the respective category was clicked in the home page (NextJs was not triggering the re-render on the server).

The solution was to use windo.location.href instead of router.push to go back to the home page after the purchase and force a full reload of the page, but the user experience/navigation was not nice.

Find below the code implemented.

import axios from "axios";
import FilteredClasses from "../../_components/FilteredClasses";
import config from "../../_lib/config";
import { addPreSignedUrlToArray } from "@/_lib/S3Helper";
import { cookies } from 'next/headers';
import '../../_styles/main.css';
import { PrimitiveTypeProp } from "@/_types/global";

export const dynamic = 'force-dynamic';

export default async function CategoryClasses({ params }: { params: PrimitiveTypeProp<String> }){

    const { category } = params;

    const cookieStore = cookies();
    const userInfoCookie = cookieStore.get('userInfo');

    let response;

    try {
        const userInfo = userInfoCookie !== undefined ? JSON.parse(userInfoCookie!.value) : null;
        const objEmail = userInfo ? {email: userInfo!.email} : null

        const apiUrl = `${config.serverEndpoint}classes/category/${category}`

        const axiosConfig = {
            headers: {
                'Cache-Control': 'no-cache',
            },
        };

        if (objEmail) {
            // the parameters object needs to be called "params" in axios
            response = await axios.get(apiUrl, {
                ...axiosConfig,
                params: objEmail,
            });
        } else {
            response = await axios.get(apiUrl, axiosConfig);
        }

    } catch (error) {
        console.error('Error fetching category classes:', error);
        response = { data: { categoryTitle: "", classes: [] } };
    }

    const classesPreSignedUrl = await addPreSignedUrlToArray(response.data.classes, 'vegan-mundi-thumbnails');

    const { categoryTitle } = response.data;
    const classesCount = classesPreSignedUrl.length;

    return (
        <FilteredClasses images={classesPreSignedUrl} title={`${classesCount} class${classesCount !== 1 ? "es" : "" } in this category`} subTitle={`Category: ${categoryTitle}`}/>            
    )
}