'useRouter: how to render fetched data from a url with router.query as url param

I’m a beginner in nextJS trying to take advantage of its dynamic routing feature.

Here’s a brief overview of what I’m trying to achieve:

  1. makes a POST request to Django Backend which returns the ID of created object (etc. 12YVX68, P18DS37) → nextJS redirects to the url which matches with the below dynamic routing page (etc. https://example.com/draft/12YVX68/)
  2. the code below makes a GET request to backend and fetch the document data, which user will can start editing.
# src/pages/draft/[draftId].tsx

import { useEffect, useState } from 'react';
import { useRouter } from 'next/router';
import { Document } from 'src/types/models';
import fetch from 'isomorphic-unfetch';
import { GetServerSideProps } from 'next';

export const getServerSideProps: GetServerSideProps = async (context) => {
  const { query } = context;
  const { draftId } = query;
  return {
    props: {
      draftId,
    },
  };
};

const Draft = () => {
  const router = useRouter();
  const [draftData, setDraftData] = useState<Document>();

  useEffect(() => {
    if (router.isReady) {
      const { draftId } = router.query;

      fetchTemplate(draftId);
      console.log(draftData);
    }
  }, [router.isReady]);

  const fetchTemplate = async (draftId: string | string[] | undefined) => {
    const fetchURL = `http://0.0.0.0:8000/api/v1/documents/${draftId}/?format=json`;
    const data = await fetch(fetchURL);
    const tempData = await data.json();
    console.log(fetchURL);
    setDraftData(tempData);
  };

  return (
    <div>
      {/* <h1 className="text-2xl">{draftData.title}</h1> */}
    </div>
  );
};

export default Draft;

This is the problem I’m having and how I’ve tried to solve it:

  1. With the help of this post, I used router.ready feature to wait until nextJS is done prerendering to display the fetched data. Previously, router.query was repeatedly returning undefined.
  2. When I uncomment any rendering code that uses the fetched data, the below error shows up. if I comment all rendering code like I did above, I get the desired fetched data logged into the console.
[draftId].tsx?99e8:40 Uncaught TypeError: Cannot read properties of undefined (reading 'title')
    at Draft ([draftId].tsx?99e8:40:43)
    at renderWithHooks (react-dom.development.js?ac89:14985:1)
    at mountIndeterminateComponent (react-dom.development.js?ac89:17811:1)
    at beginWork (react-dom.development.js?ac89:19049:1)
    at HTMLUnknownElement.callCallback (react-dom.development.js?ac89:3945:1)
    at Object.invokeGuardedCallbackDev (react-dom.development.js?ac89:3994:1)
    at invokeGuardedCallback (react-dom.development.js?ac89:4056:1)
    at beginWork$1 (react-dom.development.js?ac89:23964:1)
    at performUnitOfWork (react-dom.development.js?ac89:22776:1)
    at workLoopSync (react-dom.development.js?ac89:22707:1)
    at renderRootSync (react-dom.development.js?ac89:22670:1)
    at performSyncWorkOnRoot (react-dom.development.js?ac89:22293:1)
    at eval (react-dom.development.js?ac89:11327:1)
    at unstable_runWithPriority (scheduler.development.js?bcd2:468:1)
    at runWithPriority$1 (react-dom.development.js?ac89:11276:1)
    at flushSyncCallbackQueueImpl (react-dom.development.js?ac89:11322:1)
    at flushSyncCallbackQueue (react-dom.development.js?ac89:11309:1)
    at flushSync (react-dom.development.js?ac89:22467:1)
    at scheduleRefresh (react-dom.development.js?ac89:24429:1)
    at Object.renderer.scheduleRefresh (react_devtools_backend.js:6402:16)
    at eval (react-refresh-runtime.development.js?7e84:304:1)
    at Set.forEach (<anonymous>)
    at Object.performReactRefresh (react-refresh-runtime.development.js?7e84:293:1)
    at eval (helpers.js?7e26:125:1)


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source