reactjsnext.jsreact-propsgetserversideprops

getServerSideProps is outputting data in pages file but not in components files through props


I have this project where I am getting all the backend data from utils/api.js and then using getServerSideProps to retrieve it in the pages/index.js file then passing it through props to the several components that were passed to the pages/index.js. However, console-logging the data in the index.js page works fine but but console-logging the props in the components returns undefined. Pay attention to all the console.log in the index.js page, they all return data but not the one in the component in this case we will be using container/expertises.js as example

utils/api.js

import axios from "axios";

const ABOUT_API_URL = `${process.env.NEXT_PUBLIC_PYTHON_BACKEND_URL}/about/abouts/`;
const EXPERTISE_API_URL = `${process.env.NEXT_PUBLIC_PYTHON_BACKEND_URL}/expertise/expertise/`;
const PROJECTS_API_URL = `${process.env.NEXT_PUBLIC_PYTHON_BACKEND_URL}/project/projects`;

export const fetchAbouts = async () => {
  try {
    const response = await axios.get(ABOUT_API_URL);
    return response.data;
  } catch (error) {
    console.error("Error fetching abouts:", error);
    return null;
  }
};

export const fetchExpertise = async () => {
  try {
    const response = await axios.get(EXPERTISE_API_URL);
    return response.data;
  } catch (error) {
    console.error("Error fetching expertise:", error);
    return [];
  }
};

export const fetchProjects = async () => {
  try {
    const response = await axios.get(PROJECTS_API_URL);
    return response.data;
  } catch (error) {
    console.error("Error fetching projects:", error);
    return [];
  }
};

pages/index.js

import { Navbar } from "@/components";
import { Expertises, Footer, Header, Testimonial, Work } from "@/container";
import Articles from "@/container/Articles/Articles";
import styles from "@/styles/homescreen.module.scss";
import { fetchAbouts, fetchExpertise, fetchProjects } from "@/utils/api";
import Head from "next/head";

export async function getServerSideProps() {
  try {
    const abouts = await fetchAbouts();
    const expertise = await fetchExpertise();
    const projects = await fetchProjects();

    console.log("Fetched Abouts:", abouts);
    console.log("Fetched Expertise:", expertise);
    console.log("Fetched Projects:", projects);

    return {
      props: {
        aboutsData: abouts || [],
        expertiseData: expertise || [],
        projectsData: projects || [],
      },
    };
  } catch (error) {
    console.error("Error fetching data:", error);
    return {
      props: {
        aboutsData: [],
        expertiseData: [],
        projectsData: [],
      },
    };
  }
}

export default function Homescreen({
  aboutsData,
  expertiseData,
  projectsData,
}) {
  console.log("expertise", expertiseData);
  return (
    <>
      <div
        className={`${styles.homescreen} flex flex-col items-center justify-center`}
      >
        <Navbar />
        <Header />
        {console.log("Passing expertiseData to Expertises:", expertiseData)}
        <Expertises expertise={expertiseData} />
        <Work works={projectsData} />
        <Articles abouts={aboutsData} />
        <Testimonial />
        {/* <h2 className="head-text mt-16">Take a coffee & chat with us</h2> */}
        <div className={styles.footerbg}>
          <div className={styles.footerbg_div}>
            <Footer />
          </div>
        </div>
      </div>
    </>
  );
}

container/Expertise/Expertises.jsx

import React, { useState, useEffect, useRef } from "react";
import { motion } from "framer-motion";
import { AppWrap, MotionWrap } from "../../wrapper";
import styles from "./Expertise.module.scss";
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";
import "swiper/css/pagination";
import { Pagination } from "swiper/modules";

const Expertises = ({ expertise }) => {
  const swiperRef = useRef(null);
  console.log("container expertise", expertise);

  return (
    <>
      <div className={styles.app__expertises}>
        <Swiper
          slidesPerView={"auto"}
          centeredSlides={true}
          spaceBetween={30}
          pagination={{
            clickable: true,
          }}
          modules={[Pagination]}
          className={styles.app__skills_container}
        >
          {expertise?.slice(0, 6).map((exp, i) => (
            <SwiperSlide key={i} className={styles.app__skills_item}>
              <h3 style={{ color: exp.name.split(".")[1] }}>
                {exp.name.split(".")[0]}
              </h3>
              <p className="text-center w-full">{exp.description}</p>
              <li className={styles.list}>
                {exp.img_url.map((item, index) => (
                  <div key={index}>
                    <div key={index} className={`${styles.img_div} app__flex`}>
                      <img src={item.url} alt={item.name} />
                    </div>
                    <p className="p-text">{item.name.split(".")[0]}</p>
                  </div>
                ))}
              </li>
            </SwiperSlide>
          ))}
        </Swiper>
      </div>
    </>
  );
};

export default MotionWrap(Expertises, "app__expertises");

The console.log in expertises returns undefined

wrapper/MotionWrap.js

import React from "react";
import {motion} from 'framer-motion'


const MotionWrap = (Component, classNamaes) => function HOC() {
  return (
    <div>
      <motion.div
      whileInView={{y: [100, 50,0], opacity: [0, 0, 1]}}
      transition={{duration: 0.5}}
      className={`${classNamaes} app__flex`}
      >
        <Component />
      </motion.div>
    </div>
  )
}

export default MotionWrap

Solution

  • Just like I had guessed, the MotionWrap HOC isn't properly forwarding the props to the wrapped component and this is why the expertise prop was coming through as undefined. Here is an updated adjustment to your MotionWrap HOC:

    import React from "react";
    import { motion } from "framer-motion";
    
    const MotionWrap = (Component, classNames) => {
      return function HOC(props) {
        return (
          <div>
            <motion.div
              whileInView={{ y: [100, 50, 0], opacity: [0, 0, 1] }}
              transition={{ duration: 0.5 }}
              className={`${classNames} app__flex`}
            >
              <Component {...props} />
            </motion.div>
          </div>
        );
      };
    };
    
    export default MotionWrap;
    

    I believe with this adjustment, the expertise prop should no longer come through as undefined.