Next.js获取和维护所有组件的全局数据

21
在我的Next.js应用中,我需要进行API调用,并返回JSON响应以供所有组件使用。因此,我将避免在组件中对同一API进行多次调用。有什么正确的方法来实现这一点?

1
请提供更多上下文,包括一些代码。因为这个问题非常广泛,所以很难回答。 - Arnaud Claudel
@ArnaudClaudel 感谢您的友好回复。我需要一些帮助来维护从API调用中获取的所有组件的全局数据。 - Jayanth
2个回答

27

根据应用程序的范围而定。
如果是较大的应用程序,建议像Moshin Amjad所说的那样采用状态管理器Redux。

如果是较小的应用程序,则可以尝试使用React上下文API来管理它。
我将用最简单的方式创建一个示例,使用函数组件,利用getStaticProps而不是getInitialProps来获取静态生成的页面。

开始创建一个简单的上下文

libs/context.js

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

然后使用useState hook(或更好的是,根据数据结构使用useReducer)将从getStaticProps(或getInitialProps)获取的数据填充到其中,并将其传递给上下文提供程序。

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>
   )
}

组件/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>
   )
}

这还没有经过测试,但你可以理解一下。
最终,你可以将上下文提供程序移动到高阶组件中以包装每个页面,甚至位于pages/_app.js中,如果您需要在更高级别获取数据。

记住,如果应用程序扩展,您应该考虑使用Redux之类的东西。


很好的方法,有人可以测试并确认它能够工作吗? - tblancog
嘿,Stefano,我们能否将数据从 server.js 传递到 _app.js 或页面组件中? - avocado
5
我需要相同的东西,但我认为如果用户的第一页不是根目录,这种方法可能行不通。 - ktravelet
2
不幸的是,这些方法忽略了结果将在客户端处理,因此不利于SEO。 - insivika

0
使用redux将状态存储在全局存储中,以便多个组件可以访问,这是您的用例的常见模式。还有一个next-wrapper适用于此,链接如下:next-redux-wrapper redux。请保留HTML标签。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接