Search code examples
reactjsjsxnext.jsnext-router

In NextJS Is it possible to have custom _app.js read a slug, getInitialProps and pass those props to every component including all pages?


I have looked around the docs to see if I can have _app.js read a slug (nothing mentioned about it). I need this slug to be added to an HTTP get request to grab the proper data that then then returns results to _app.js in which I can then use to pass props to all components and pages.

Example: when I go to http://localhost:3000/some-business-name , _app.js can grab the slug (some-business-name), do the request, and pass props to all components and pages in the project.

But what I am really struggling to do is get the App props to pass to all the rest of the pages inside the pages folder.

In my pages folder I have:

  1. _app.js -- (what I need to pass props to all pages)
  2. [slug].js -- (root page that used to detect slug and now I need for it to just receive props from _app.js)
  3. success.js -- (need to receive props from _app.js)
  4. error.js -- (need to receive props from _app.js)

I am using a data file that is an array of business data objects to which I use to test dynamic routing with.

I have looked in the NextJS docs and I am having an issue understanding how this can be done. I still need for the slug to exist, I just need help understanding how I can get _app.js to completely take over dynamic routing.

My code for _app.js is:

import React from 'react'
import App from 'next/app'
import { businesses } from '../data';

export default function MyApp({ Component, appProps }) {
  return (
    <Component appProps={appProps} />
  )
};

MyApp.getInitialProps = async ({ appContext }) => {
  const appProps = await App.getInitialProps(slug);
  return {appProps};
};

App.getInitialProps = async (slug) => {
  const business = businesses.filter((business) => {
    return business.slug === slug;
  });
  return business[0];
};

Currently my [slug].js is:

import React from 'react';
import Head from 'next/head';
import LandingPage from '../components/landing-page';

export default function Slug(props) {
  return (
    <div>
      <Head>
        <title>Home</title>
        <link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css' integrity='sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm' crossOrigin='anonymous' />
        <link href='https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300;0,400;0,600;0,700;0,800;1,300;1,400;1,600;1,700;1,800&display=swap' rel='stylesheet' />
        <script src='https://code.jquery.com/jquery-3.2.1.slim.min.js' integrity='sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN' crossOrigin='anonymous'></script>
        <script src='https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js' integrity='sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q' crossOrigin='anonymous'></script>
        <script src='https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js' integrity='sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl' crossOrigin='anonymous'></script>
      </Head>

      <LandingPage businessInfo={props.appProps}/>

      <style global jsx>{`
          body {
            font-family: 'Open Sans', sans-serif;
          }
        `}</style>
    </div>
  );
};

Surprisingly I am able to receive App props on the LandingPage component in [slug].js but not in the success.js and error.js pages.

Any help is extremely appreciated! Thanks!


Solution

  • You can use something like this:

    import React from 'react'
    import App from 'next/app'
    import { Router } from '../routes'
    
    class MyApp extends App {
      // Only uncomment this method if you have blocking data requirements for
      // every single page in your application. This disables the ability to
      // perform automatic static optimization, causing every page in your app to
      // be server-side rendered.
      //
      // static async getInitialProps(appContext) {
      //   // calls page's `getInitialProps` and fills `appProps.pageProps`
      //   const appProps = await App.getInitialProps(appContext);
      //
      //   return { ...appProps }
      // }
    
      render() {
        const { Component, appProps } = this.props
        // Workaround for https://github.com/zeit/next.js/issues/8592
        const { err } = this.props
        const modifiedPageProps = { ...appProps, err }
        return (
            <div id="comp-wrapp">
              <Component {...modifiedPageProps} />
            </div>
        )
      }
    }
    
    export default MyApp