I'm working on a next.js app and my page layout is going through the following hierarchy:
_app.js
Page.js
Header.js
PageContent.js
I need to pass some parameters from PageContent to Header without using redux.
Inside _app.js I have the following:
class Main extends App {
render() {
const {
Component,
pageProps,
apollo,
router: { route }
} = this.props;
return (
<ApolloProvider client={apollo}>
<Page
pathname={route.split("/")[1]}
{...pageProps}
localLinks={Component.LocalLinks}
render={props => <Component {...props} />}
/>
</ApolloProvider>
);
}
}
I'm assuming there should be a way to pass some propse (pageProps) from PageContent to _app and pass that down to Page and make them accessible to header. Is there a next.js specific trick here that I'm not familiar with?
I'm working on a next.js app and my page layout is going through the following hierarchy:
_app.js
Page.js
Header.js
PageContent.js
I need to pass some parameters from PageContent to Header without using redux.
Inside _app.js I have the following:
class Main extends App {
render() {
const {
Component,
pageProps,
apollo,
router: { route }
} = this.props;
return (
<ApolloProvider client={apollo}>
<Page
pathname={route.split("/")[1]}
{...pageProps}
localLinks={Component.LocalLinks}
render={props => <Component {...props} />}
/>
</ApolloProvider>
);
}
}
I'm assuming there should be a way to pass some propse (pageProps) from PageContent to _app and pass that down to Page and make them accessible to header. Is there a next.js specific trick here that I'm not familiar with?
Share Improve this question asked Jan 10, 2020 at 1:43 Adam BoostaniAdam Boostani 6,23310 gold badges40 silver badges44 bronze badges 1- I am not familiar with next.js, but in React you can just lift the state up, so your children will have access to modify those props that could be shared between sibling ponents: reactjs/docs/lifting-state-up.html – Bruno Monteiro Commented Jan 10, 2020 at 2:04
2 Answers
Reset to default 1You can use context api or Parent container state (here Page ponent).
First Way -> Use context api
Second Way
- make State on page ponent
- pass StatemodifierFunction props to pageContent
- then modify state by calling this StatemodifierFunction
- then pass this state to Header Component
** Third way **
- you can use react node also
Here's a full example with contexts (approach previously suggested in this other answer by slightly modifying https://github./vercel/next.js/tree/7df7c5e80515eea6745fd59e54d87e5ee709fe0c/examples/with-app-layout tested on Next.js 12.0.7 and React 17:
pages/_app.js
import React from 'react'
export const MyAppContext = React.createContext({
n: 0,
setN: undefined,
});
function Header(props) {
return <div>n = { props.n }</div>
}
export default function App({ Component, pageProps }) {
const [n, setN] = React.useState(0)
return (
<MyAppContext.Provider value={{n, setN}}>
<Header n={n} />
<Component {...pageProps} />
</MyAppContext.Provider>
)
}
pages/index.js
import { MyAppContext } from './_app.js'
import React from 'react'
export default function Home() {
const {n, setN} = React.useContext(MyAppContext)
React.useEffect(() => {
setN(new Date().getTime())
}, [])
return <div>test</div>
}
package.json
{
"name": "with-app-layout",
"version": "1.0.0",
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
},
"dependencies": {
"next": "12.0.7",
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"license": "MIT"
}
and run with:
npm install
npm run dev
The useEffect
is required otherwise you will get the error:
Cannot update a ponent (`App`) while rendering a different ponent (`Home`)
which is mentioned at: Cannot update a ponent while rendering a different ponent warning Basically you cannot call .set
methods directly from render
.
If it's something that depends only on the page and not props
The following works without contexts, I wonder if setting such attributes could cause any problems down the line:
pages/_app.js
function Header(props) {
return <div>n = { props.n }</div>
}
export default function App({ Component, pageProps }) {
return (
<>
<Header n={Component.n} />
<Component {...pageProps} />
</>
)
}
pages/index.js
export default function Home() {
return <div>test</div>
}
Home.n = 1