简体   繁体   中英

How to pass data fetched in _app.js to a component

In my nextjs project, I have the Layout component that needs api call. Instead of calling api calls in every pages(./pages/*), I'd like to put the logic in some global space. I researched a bit, and it looks like overriding _app.js is the way to go indicated in nextjs documentation( https://nextjs.org/docs/advanced-features/custom-app ).

I have laid out code as below. But it doesn't seem to work.

./pages/_app.js

function MyApp({ Component, appProps, results }) {

  return (
    <Layout {...results}>
      <Component {...appProps} />
    </Layout>
  )
}

MyApp.getInitialProps = async (appContext) => {
  const appProps = await App.getInitialProps(appContext)
  const results = await getResults()  //api call

  return { appProps, results }
}

./components/Layout.js

const Layout = ({ children, results }) => {

  return (
    <React.Fragment>
      <Header/>
      <div className='row col-md-8 offset-md-2'>
        {JSON.stringify(results)} //results is nothing here
        <div className='col-md-9'>
          {children}
        </div>
      </div>
    </React.Fragment>
  )
}

./pages/index.js

...
return (
    <>
      {head()}
      <Layout>
        <div className='row col-md-12'>
          {showContents()}
        </div>
      </Layout>
    </>
  )

I'm sure I'm missing some obvious things. Any help would be appreciated.

Unless you're intending to have that page return similar results every time, you should migrate your api call on the client side. Next.JS has moved away from getInitialProps in favour of getStaticProps (fetch static data), getStaticPaths (pre-render a set of static pages) and getServerSideProps (this is probably closest to getInitialProps, fetching data on the server-side). More info on next.js data fetching here: https://nextjs.org/docs/basic-features/data-fetching

Now to answer your question based on the code you provided

// index.js
<Layout> <- you're not passing any props here.

It should prop the results down like so:

// index.js
function Page({ results }){
  return <Layout results={results}>Hello</Layout>
}

With the client-side example, you can do something like

import { useState } from 'react'

function useCats(){
  const [cats, setCats] = useState()
  useEffect(() => {
    fetch('https://test.api/cats')
      .then(response => response.json())
      .then(_cats => setCats(_cats));
  }, [])

  return cats
}

// then in another component

function CatsList(){
  const cats = useCats();
  if(!cats){
    return <p>Loading</p>
  }

  return <div>
    {cats.map(cat => <p key={cat.id}>Cat: {cat.name}</p>)}
  </div>
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM