admin 管理员组

文章数量: 1086019

I'm working on my first serious NextJS app. I have it set up to pull in JSON data for the left nav, rather than hardcoding them in the app somewhere. This way I don't have to rebuild every time there's a minor change to the site's navigation.

Since the navigation needs to be available on every page, I added getInitialProps to the _app.js file, which grabs the left nav and passes it to the left nav ponent. But now as I'm moving on to build the homepage, I see that the getInitialProps there does not run. It seems that the getInitialProps in _app.js takes precendence.

Is there a way to have both? Or some other workaround that acplishes the goal (or just a better way to do this in general)?

Note that I'm using getInitialProps for two reasons:

  1. getStaticProps is out because I don't plan to build the entire site at build time
  2. getServerSideProps is usually out because I don't like that it ends up doing two http requests: first a request goes to the NextJS server, then the server sends a request to my API (which happens to live on a different server). If I'm just getting basic stuff like the navigation, there's no need for getServerSideProps to run on the NextJS server, I'd rather skip the middle man

Here's some some simplified code:

_app.js:

import { Provider } from "react-redux";
import axios from "axios";

import store from "../store";
import Header from "../ponents/Header";
import LeftNav from "../ponents/LeftNav";

function MyApp(props) {
    const { Component, pageProps } = props;

    return (
        <Provider store={store}>
            <Header />
            <LeftNav leftnav={props.leftnav} />
            <Component { ...pageProps } />
        </Provider>
    )
}

MyApp.getInitialProps = async (context) => {
    let config = await import("../config/config");
    let response = await axios.get(`${config.default.apiEndpoint}&cAction=getLeftNav`);

    if (response) {
        return {
            leftnav: response.data.leftNav
        };
    } else {
        return {
            leftnav: null
        };
    }
};

export default MyApp;

Home.js:

import axios from "axios";

const Home = (props) => {
    console.log("Home props", props);
    return (
        <div>home</div>
    );
};

Home.getInitialProps = async(context) => {
    
    // this only runs if the getInitialProps in _app.js is removed :(

    let config = await import("../config/config");
    let response = await axios.get( `${config.default.apiEndpoint}&cAction=getHome` );
    if ( response ) {
        return {
            home: response.data.home
        };
    } else {
        return {
            home: null
        }
    }
};
export default Home;

I'm working on my first serious NextJS app. I have it set up to pull in JSON data for the left nav, rather than hardcoding them in the app somewhere. This way I don't have to rebuild every time there's a minor change to the site's navigation.

Since the navigation needs to be available on every page, I added getInitialProps to the _app.js file, which grabs the left nav and passes it to the left nav ponent. But now as I'm moving on to build the homepage, I see that the getInitialProps there does not run. It seems that the getInitialProps in _app.js takes precendence.

Is there a way to have both? Or some other workaround that acplishes the goal (or just a better way to do this in general)?

Note that I'm using getInitialProps for two reasons:

  1. getStaticProps is out because I don't plan to build the entire site at build time
  2. getServerSideProps is usually out because I don't like that it ends up doing two http requests: first a request goes to the NextJS server, then the server sends a request to my API (which happens to live on a different server). If I'm just getting basic stuff like the navigation, there's no need for getServerSideProps to run on the NextJS server, I'd rather skip the middle man

Here's some some simplified code:

_app.js:

import { Provider } from "react-redux";
import axios from "axios";

import store from "../store";
import Header from "../ponents/Header";
import LeftNav from "../ponents/LeftNav";

function MyApp(props) {
    const { Component, pageProps } = props;

    return (
        <Provider store={store}>
            <Header />
            <LeftNav leftnav={props.leftnav} />
            <Component { ...pageProps } />
        </Provider>
    )
}

MyApp.getInitialProps = async (context) => {
    let config = await import("../config/config");
    let response = await axios.get(`${config.default.apiEndpoint}&cAction=getLeftNav`);

    if (response) {
        return {
            leftnav: response.data.leftNav
        };
    } else {
        return {
            leftnav: null
        };
    }
};

export default MyApp;

Home.js:

import axios from "axios";

const Home = (props) => {
    console.log("Home props", props);
    return (
        <div>home</div>
    );
};

Home.getInitialProps = async(context) => {
    
    // this only runs if the getInitialProps in _app.js is removed :(

    let config = await import("../config/config");
    let response = await axios.get( `${config.default.apiEndpoint}&cAction=getHome` );
    if ( response ) {
        return {
            home: response.data.home
        };
    } else {
        return {
            home: null
        }
    }
};
export default Home;
Share Improve this question asked Jun 30, 2021 at 21:57 Mike WillisMike Willis 1,52216 silver badges37 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 8

You have to call App.getInitialProps(context) in your _app to call the current page's getInitialProps. You can then merge the page's props with the remaining props from _app.

import App from 'next/app'

// Remaining code...

MyApp.getInitialProps = async (context) => {
    const pageProps = await App.getInitialProps(context); // Retrieves page's `getInitialProps`
    
    let config = await import("../config/config");
    let response = await axios.get(`${config.default.apiEndpoint}&cAction=getLeftNav`);

    return {
        ...pageProps,
        leftnav: response?.data?.leftNav ?? null
    };
};

From the custom _app documentation:

When you add getInitialProps in your custom app, you must import App from "next/app", call App.getInitialProps(appContext) inside getInitialProps and merge the returned object into the return value.

本文标签: javascriptCan I use getInitialProps in appjs and in pagesStack Overflow