Next.js すべてのコンポーネントのグローバルデータを取得して維持する 質問する

Next.js すべてのコンポーネントのグローバルデータを取得して維持する 質問する

Next.js アプリでは、すべてのコンポーネントで使用する必要のある JSON 応答を返す API 呼び出しを行う必要があります。したがって、コンポーネント内で同じ API を複数回呼び出すことは避けます。これを実現する適切な方法は何ですか?

ベストアンサー1

アプリケーションの範囲によって異なります。
大規模なアプリケーションの場合は、Moshin Amjad 氏が言うように、Redux のような状態マネージャーを採用したほうがよいでしょう。

より小規模なアプリであれば、React コンテキスト API を使用して管理してみることもできます。静的に生成されたページを取得するために、 の代わりに
を利用して、関数コンポーネントを使用する最も簡単な方法の例を示します。getStaticPropsgetInitialProps

シンプルなコンテキストの作成を開始する

libs/context.js

import React from "react";
export const Context = React.createContext();

次に、 getStaticProps (または getInitialProps) から取得したデータを使用してuseStateフック (または、useReducerデータの構造に応じてフックの方が適切) を設定し、それをコンテキスト プロバイダーに渡します。

pages/index.js

import React from 'react'
import { Context } from "../libs/context.js"

import Title from "../components/Title"
import Button from "../components/Button"

// data will be populated at build time by getStaticProps()

function Page({ data }) {
    const [ context, setContext ] = React.useState(data)
    return (
        <Context.Provider value={[context, setContext]}>
            <main>
                <Title />
                <Button />
            </main>
        </Context.Provider>
    )
}

export async function getStaticProps(context) {

  // fetch data here
  const data = await fetchData()

  // Let's assume something silly like this:
  // {
  //     buttonLabel: 'Click me to change the title',
  //     pageTitle: 'My page'
  // }
  
  return {
    props: {
       data
    }, // will be passed to the page component as props
  }
}

そして最後に、プロバイダーの任意の子でそれを使用(または変更)します。

components/Title.js

import React, { useContext } from "react"
import { Context } from "./Context"

export default function MyComponent() {
   const [context, setContext] = useContext(Context)
   
   return (
       <h1>{context.pageTitle}</h1>
   )
}

components/Button.js

import React, { useContext } from "react"
import { Context } from "./Context"

export default function MyComponent() {
   const [context, setContext] = useContext(Context)
   
   function changeTitle() {
      preventDefault();
      setContext(oldContext => ({ 
          ...oldContext, 
          pageTitle: 'New page title!' 
      }))
   }

   return (
       <div>
          <button onClick={changeTitle}>{context.buttonLabel}</button>
       </div>
   )
}

まだテストされていませんが、考え方はわかります。
最終的には、コンテキスト プロバイダーを High Order Component に移動して、すべてのページをラップしたり、pages/_app.jsより高いレベルのデータが必要な場合はそのコンポーネントに移動したりすることもできます。

アプリが拡張される場合は、Redux のようなものを検討する必要があることに注意してください。

おすすめ記事