I have a custom _app.js
:
const Layout = ({ children }) => (children);
const app = ({ Component, pageProps }) => {
pageProps.baseUrl = 'some url';
return (
<Layout>
<Component {...pageProps} />
</Layout>
)
};
And a page:
export async function getServerSideProps({ req, query, res, baseUrl }) {
// baseUrl is undefined and an error, if I am using it with destructiring
console.log(req) // There is no baseUrl
return { props: { ..... } }
}
I want to set that pageProps.baseUrl= 'some url';
in _app.js
and use it in page ponents including getServerSideProps
, how can I do that ?
I have a custom _app.js
:
const Layout = ({ children }) => (children);
const app = ({ Component, pageProps }) => {
pageProps.baseUrl = 'some url';
return (
<Layout>
<Component {...pageProps} />
</Layout>
)
};
And a page:
export async function getServerSideProps({ req, query, res, baseUrl }) {
// baseUrl is undefined and an error, if I am using it with destructiring
console.log(req) // There is no baseUrl
return { props: { ..... } }
}
I want to set that pageProps.baseUrl= 'some url';
in _app.js
and use it in page ponents including getServerSideProps
, how can I do that ?
2 Answers
Reset to default 3For now, I have created a file, which contains all global values like this:
let store = {};
const globalStore = {};
globalStore.set = (key, value) => {
store = { ...store, [key]: value };
}
globalStore.get = (key) => {
return store[key];
}
export default globalStore;
Then in _app.js
import it and set a value:
const app = ({ Component, pageProps }) => {
globalStore.set('baseUrl', 'some url 1');
globalStore.set('baseUrl2', 'some url 2');
return (
<Layout>
<Component {...pageProps} />
</Layout>
)
}
import the file in pages/index.js
and inside the ponent or getServerSideProps
:
export async function getServerSideProps({ req, query, res }) {
console.log('in getServerSideProps');
console.log(globalStore.get('baseUrl'));
console.log(globalStore.get('baseUrl2'));
...
I think, in this particular case, it's ok to use constants here instead of props.
Proposed solution
In constants.js:
export const BASE_URL = 'some url';
And in your page:
import * as Constants from '../path/to/constants';
export async function getServerSideProps({ req, query, res }) {
// use Constants.BASE_URL here
return { props: { ..... } }
}
Why won't props work the way you want them to?
Your page ponent and the getServerSideProps method you export from the file are separate, and are executed at different times. Rendering your ponent does not call getServerSideProps. I believe the order in Next.js is like this:
- A request is made at a route.
- Next.js looks at the file in
pages/
for the corresponding route - Next.js will run the appropriate method based on the execution context (on a server render, getServerSideProps)
- Next.js renders the App ponent, passing it the pageProps provided from getServerSideProps
- The App ponent renders the Page ponent
In this case, you have created a paradox. Think about how the props flow:
- getServerSideProps runs, returns a pageProps object
- App ponent renders, containing the pageProps object passed from getServerSideProps
- Page ponent renders, passed the pageProps
If getServerSideProps is responsible for creating the pageProps object, it can't also be passed that object as an argument.