0
votes

I am building a project using next.js but I have an issue that getServerSideProps is called 6 times when the page is rendered.

Here is the code at the top in pages.

const NewFindstay: React.FC<INewFindstayProps> = ({ findstayList }) => {
  const [isMap, setIsMap] = useState(false);
  return (
    <div id="contents">
      <FindstayFilter setIsMap={setIsMap} isMap={isMap} />
      <FindstayList findstayList={findstayList} isMap={isMap} />
    </div>
  );
};

export async function getServerSideProps({ query, req }) {
  let findstayList = null;
  try {
    findstayList = await getPlaceListAsync(
      { ...query },
      req.headers.cookie ? req.headers.cookie : null
    );
  } catch (e) {
    findstayList = null;
  }
  return {
    props: {
      findstayList,
      query,
    },
  };
}

export default NewFindstay;

Seems this is caused by components that imported inside of FindstayFilter. (let's say components A, B, C, D, E, F)

Each components of A, B, C, D, E, F has useEffect hook for setState.

// A
 useEffect(() => {
    if (router.query.city) {
      setSelectedCity(router.query.city);
    };
  }, [router.query.city]);

// B
  useEffect(() => {
    setDateRange({
      startDate: check_in ? moment(check_in) : null,
      endDate: check_out ? moment(check_out) : null
    })
  }, [router.query.check_in, router.query.check_out]);
// C
  useEffect(() => {
    const queryPrice = {
      min: price_min ? (parseInt(price_min as string, 10) / 10000) : 0,
      max: price_max ? (parseInt(price_max as string, 10) / 10000) : 100
    }
    setRangePrice(queryPrice);
  }, [router.query.price_min, router.query.price_max]);

// D, E, F use same pattern as well.

In order words, when FindstayFilter component renders, useEffect hook inside A, B, C, D, E, F rerender the component total 6 times which triggers calling getServerSideProps 6 times as well.

How can I minimize calling getServerSideProps? should I use useEffect hook only inside of FindstayFilter component and crammed many setstate code into the hook?

2

2 Answers

0
votes

getServerSideProps is only called when the page first loads because it will call the nodejs server of nextjs. That will be always the case no mater what, unless you do some reloading/refreshing the page. https://nextjs.org/docs/basic-features/data-fetching#getserversideprops-server-side-rendering

0
votes

I have found what was wrong.

I put useEffect hook with dependency array state inside in every component so that whenever states changes, router.push works.

  const pushRouter = (renderQuery) => {
    return (
      router.push({
        pathname: "/findstay",
        query: {
          ...router.query,
          ...renderQuery,
          page: 1,
          per: 10
        }
      })
    );
  };

  useEffect(() => {
    const queryCnt = {
      adultCnt: adult_cnt ? parseInt(adult_cnt as string, 10) : 0,
      childCnt: child_cnt ? parseInt(child_cnt as string, 10) : 0,
      babyCnt: baby_cnt ? parseInt(baby_cnt as string, 10) : 0
    };
    pushRouter(queryCnt)
  }, [adult_cnt, child_cnt, baby_cnt]);

However router.push works as ssr in my code(it is supposed to work as csr) which means when FindstayFilter renders, pushRouter function in children components A, B, C, D, E, F also works and this leads to getServerSideProps renders 6 times.

Now I have to find a reason why router.push works ssr https://github.com/vercel/next.js/issues/9586