NextJS routing error, when changing pages, the wrong file is trying to open

1.7k views Asked by At

What I want

I want to change pages without next thinking I am trying to open another page.

The Problem

I have this weird routing problem. First, my folder structure

pages
  [app]
    [object]
      index.js
    index.js
    manager.js
    feed.js

I am at this path /[app] and navigate to /[app]/manager and then I want to navigate to /[app]/feed and I get this Unhandled Runtime Error.

TypeError: Cannot read property "title" of undefined

This error comes from [object] index.js. Stacktrace is below. Of course, it makes sense it cannot read title because I am trying to open another page. And yet it thinks I am trying to open [object]. This error happens from time to time, but it doesn't matter in what order I try to open the pages, it can be manager to feed or feed to manager, or whatever else I have there. My getStaticPaths and getStaticProps are the same on all these pages, I will share the one for manager.js.

export const getStaticPaths = async () => {
  const paths = appRoutes.map((appRoute) => {
    const slug = appRoute.slug;

    return {
      params: {
        app: slug,
        manager: 'manager',
      },
    };
  });

  return {
    fallback: false,
    paths,
  };
};

export const getStaticProps = async ({ locale }) => {
  return {
    props: {
      ...(await serverSideTranslations(locale, ['manager', 'common'])),
    },
  };
};

And the same again, but for [object]:

export const getStaticPaths = async () => {
  const allObjects = await loadObjectData({ id: 'all' });
  const paths = allObjects.flatMap((object) => {
    return appRoutes.map((appRoute) => {
      return {
        params: {
          object: object.type,
          app: appRoute.slug,
        },
      };
    });
  });

  return {
    fallback: false,
    paths,
  };
};

export const getStaticProps = async ({ params, locale }) => {
  const object = await loadObjectData({ type: params.object });
  const app = appRoutes.find((appRoute) => appRoute?.slug === params.app);

  if (!object) {
    throw new Error(
      `${object} is not a valid Object. Try checking out your parameters: ${params.object}`
    );
  }

  if (!app) {
    throw new Error(`${app} is not a valid App.`);
  }

  return {
    props: {
      ...(await serverSideTranslation(locale, ['common'])),
      object,
      app,
    },
  };
};

This error is hard to reproduce because it happens only from time to time.


New Edits

This is the full file of [object]/index.js

import appRoutes from '../../../routes/appRoutes';
import loadObjectData from '../../../utils/loadObjects';
import { serverSideTranslation } from 'next-i18next/serverSideTranslations';

export default function ObjectPage({ object }) {
  return <h1> {object.title} </h1>;
}

export const getStaticPaths = async () => {
  const allObjects = await loadObjectData({ id: 'all' });
  const paths = allObjects.flatMap((object) => {
    return appRoutes.map((appRoute) => {
      return {
        params: {
          object: object.type,
          app: appRoute.slug,
        },
      };
    });
  });

  return {
    fallback: false,
    paths,
  };
};

export const getStaticProps = async ({ params, locale }) => {
  const object = await loadObjectData({ type: params.object });
  const app = appRoutes.find((appRoute) => appRoute?.slug === params.app);

  if (!object) {
    throw new Error(
      `${object} is not a valid Object. Try checking out your parameters: ${params.object}`
    );
  }

  if (!app) {
    throw new Error(`${app} is not a valid App.`);
  }

  return {
    props: {
      ...(await serverSideTranslation(locale, ['common'])),
      object,
      app,
    },
  };
};

Stacktrace:

ObjectPage: index.js:6 Uncaught TypeError: Cannot read property 'title' of undefined

at ObjectPage (http://localhost:3000/_next/static/chunks/pages/%5Bapp%5D/%5Bobject%5D.js:3733:21)
at div
at Grid (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:13654:35)
at WithStyles (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:179881:31)
at div
at StyledComponent (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:179652:28)
at div
at ProjectSelectionStore (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:234820:77)
at Layout (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:278:23)
at TaskStore (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:235454:77)
at UserDocumentStore (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:235663:77)
at StoneStore (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:235119:77)
at StoreMall (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:409:23)
at ThemeProvider (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:178584:24)
at App (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:234333:24)
at I18nextProvider (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624290251377:224427:19)
at AppWithTranslation
at ErrorBoundary (http://localhost:3000/_next/static/chunks/main.js?ts=1624290251377:146:47)
at ReactDevOverlay (http://localhost:3000/_next/static/chunks/main.js?ts=1624290251377:250:23)
at Container (http://localhost:3000/_next/static/chunks/main.js?ts=1624290251377:8662:5)
at AppContainer (http://localhost:3000/_next/static/chunks/main.js?ts=1624290251377:9151:24)
at Root (http://localhost:3000/_next/static/chunks/main.js?ts=1624290251377:9282:24)

25.06.2021

So I consoled logged the router from the ObjectPage and for each NavigationItem. I noticed something strange.
This is the href I am passing to teh <Link>:

{
  pathname: "/[app]/[menuItem]"
  query: {
    app: "content"
    menuItem: "files"
  }
}

And this is the full router I am getting back on ObjectPage.

{
asPath: "/content/editor" // this the path i want to open
back: ƒ ()
basePath: ""
beforePopState: ƒ ()
components: {
  "/[app]/[object]": {styleSheets: Array(0), __N_SSG: true, __N_SSP: undefined, props: {…}, Component: ƒ}
  "/[app]/editor": {initial: true, props: {…}, err: undefined, __N_SSG: true, Component: ƒ, …}
  "/_app": {styleSheets: Array(0), Component: ƒ}
}
defaultLocale: "de"
events: {on: ƒ, off: ƒ, emit: ƒ}
isFallback: false
isLocaleDomain: false
isPreview: false
isReady: true
locale: "de"
locales: ["de"]
pathname: "/[app]/[object]" // [object] is being loaded
prefetch: ƒ ()
push: ƒ ()
query: {app: "content", menuItem: "editor", object: "editor"} // this is interesting
reload: ƒ ()
replace: ƒ ()
route: "/[app]/[object]" // same as pathname
}

In the query you can see object was injected. But I cannot tell from where and why.

1

There are 1 answers

0
Mähnenwolf On

I had this code:

{
  pathname: "/[app]/[menuItem]"
  query: {
    app: "content"
    menuItem: "files"
  }
}

This was incorrect because there is no dynamic path to [menuItem]. So instead I wrote:

{
  pathname: "/[app]/files"
  query: {
    app: "content"
  }
}

Which fixed the issue I had.

I have misunderstood the docs for parameters.