如何在 _app.js 中使用 getStaticProps 在 Next.js 的每个页面中显示从 api 获取的数据 [英] How to use getStaticProps in _app.js for showing data fetched from api in every pages in Next.js
问题描述
具体来说,我在导航栏上显示来自 API 端点的数据.我想使用 getStaticProps 在所有页面上获取这些数据.但问题是我需要在所有页面上执行 getStaticProps.
我们可以做这样的事情并获取所有页面上的数据作为道具吗?
//pages/_app.js功能 MyApp({ 组件, pageProps, 导航 }) {返回 (<><组件 {...pageProps} navs={navs}/></>);}导出异步函数 getStaticProps() {const res = await api.get("/api/v1/navs");常量导航= res.data;返回 {道具: {导航,},//重新验证:60,//以秒为单位};}导出默认 MyApp;
有什么替代方法可以做到这一点?有没有办法管理全局状态,以便所有页面都使用它?我不认为我们也可以使用 Context API 来为所有页面提供数据.
问题
NextJS 目前不支持 _app.js
中的生命周期方法.
解决方案
由于上述内容尚不支持,您需要创建一个可重用的 getStaticProps
函数并将其从所有页面导出.不幸的是,这确实意味着一些 WET 代码;但是,您可以通过创建一个包装页面的
代码
组件/导航
import * as React from "react";从下一个/链接"导入链接;从./Navigation.module.css"导入{ nav, navItem };常量导航 = () =>(<div 类名={nav}>{[{标题:首页",网址:/";},{ 标题:关于",网址:/about"},{ 标题:帮助",网址:/帮助";}].map(({ 标题, url }) => (<div className={navItem} key={title}><链接href={url}>{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}<a>{标题}</a></链接></div>))}</div>);导出默认导航;
组件/用户列表
import * as React from "react";从lodash.isempty"导入 isEmpty;从./UsersList.module.css"导入{ noUsers, title, userList, user };const UsersList = ({ 错误,用户,检索 }) =>!检索到?(<p>加载中...</p>) : !isEmpty(users) ?(<div 类名={userList}><h1 className={title}>静态优化的用户列表</h1>{users.map(({ name }) => (<div className={user} key={name}>{名称}</div>))}</div>) : (<div className={noUsers}>{错误 ||加载用户列表失败"}</div>);导出默认用户列表;
容器/withUsersList
import * as React from "react";从axios"导入axios;从../../components/UsersList"导入用户列表;/*** 包装页面并向其中添加 UserList 组件的 HOC.** @function withUsersList* @param Component - 一个 React 组件(页面)* @returns {ReactElement}* @example withUsersList(组件)*/const withUsersList = (组件) =>{const WrapComponent = (props) =>(<><用户列表 {...props}/><组件 {...props}/></>);返回包装组件;};导出 const getStaticProps = async () =>{尝试 {const res = await axios.get("https://jsonplaceholder.typicode.com/users");返回 {道具: {检索到:真实,用户:res.data,错误:"}};} 捕捉(错误){返回 {道具: {检索到:真实,用户:[],错误:error.toString()}};}};导出默认 withUsersList;
pages/_app.js
import * as React from "react";从../components/Navigation"导入导航;const App = ({ 组件, pageProps }) =>(<><导航/><组件 {...pageProps}/></>);导出默认应用程序;
页面/关于
import withUsersList, { getStaticProps } from "../containers/withUsersList";常量 AboutPage = () =><div>关于我们.</div>;导出 { getStaticProps };导出默认 withUsersList(AboutPage);
页面/帮助
import withUsersList, { getStaticProps } from "../containers/withUsersList";const HelpPage = () =><div>在这里寻求帮助.</div>;导出 { getStaticProps };导出默认 withUsersList(HelpPage);
页面/索引
import withUsersList, { getStaticProps } from "../containers/withUsersList";const IndexPage = () =><div>Hello World.</div>;导出 { getStaticProps };导出默认 withUsersList(IndexPage);
To be specific I am showing data on the navbar from the API endpoint. And I want to use getStaticProps to get those data on all the pages. But the problem is I need to do getStaticProps on all the pages.
Can we do something like this and get data on all the pages as props?
//pages/_app.js
function MyApp({ Component, pageProps, navs }) {
return (
<>
<Component {...pageProps} navs={navs} />
</>
);
}
export async function getStaticProps() {
const res = await api.get("/api/v1/navs");
const navs = res.data;
return {
props: {
navs,
},
// revalidate: 60, // In seconds
};
}
export default MyApp;
What could be the alternative way of doing this? Is there a way to manage a global state, so that it is used by all the pages? I don't think we can use Context API to provide data to all the pages too.
Problem
NextJS doesn't currently support lifecycle methods in _app.js
.
Solution
Since the above isn't supported yet, you'll want to create a reusable getStaticProps
function and export it from all pages. Unfortunately, this does mean some WET code; however, you can reduce some boilerplate by creating a HOC which wraps the page and also exports a getStaticProps function.
Alternatives
You can use getInitialProps
within the _app.js
file. Unfortunately, this disables automatic static optimization across the entire application.
Demo
Code
components/Navigation
import * as React from "react";
import Link from "next/link";
import { nav, navItem } from "./Navigation.module.css";
const Navigation = () => (
<div className={nav}>
{[
{ title: "Home", url: "/" },
{ title: "About", url: "/about" },
{ title: "Help", url: "/help" }
].map(({ title, url }) => (
<div className={navItem} key={title}>
<Link href={url}>
{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
<a>{title}</a>
</Link>
</div>
))}
</div>
);
export default Navigation;
components/UsersList
import * as React from "react";
import isEmpty from "lodash.isempty";
import { noUsers, title, userList, user } from "./UsersList.module.css";
const UsersList = ({ error, users, retrieved }) =>
!retrieved ? (
<p>Loading...</p>
) : !isEmpty(users) ? (
<div className={userList}>
<h1 className={title}>Statically Optimized User List</h1>
{users.map(({ name }) => (
<div className={user} key={name}>
{name}
</div>
))}
</div>
) : (
<div className={noUsers}>{error || "Failed to load users list"}</div>
);
export default UsersList;
containers/withUsersList
import * as React from "react";
import axios from "axios";
import UsersList from "../../components/UsersList";
/**
* A HOC that wraps a page and adds the UserList component to it.
*
* @function withUsersList
* @param Component - a React component (page)
* @returns {ReactElement}
* @example withUsersList(Component)
*/
const withUsersList = (Component) => {
const wrappedComponent = (props) => (
<>
<UsersList {...props} />
<Component {...props} />
</>
);
return wrappedComponent;
};
export const getStaticProps = async () => {
try {
const res = await axios.get("https://jsonplaceholder.typicode.com/users");
return {
props: {
retrieved: true,
users: res.data,
error: ""
}
};
} catch (error) {
return {
props: {
retrieved: true,
users: [],
error: error.toString()
}
};
}
};
export default withUsersList;
pages/_app.js
import * as React from "react";
import Navigation from "../components/Navigation";
const App = ({ Component, pageProps }) => (
<>
<Navigation />
<Component {...pageProps} />
</>
);
export default App;
pages/about
import withUsersList, { getStaticProps } from "../containers/withUsersList";
const AboutPage = () => <div>About Us.</div>;
export { getStaticProps };
export default withUsersList(AboutPage);
pages/help
import withUsersList, { getStaticProps } from "../containers/withUsersList";
const HelpPage = () => <div>Find Help Here.</div>;
export { getStaticProps };
export default withUsersList(HelpPage);
pages/index
import withUsersList, { getStaticProps } from "../containers/withUsersList";
const IndexPage = () => <div>Hello World.</div>;
export { getStaticProps };
export default withUsersList(IndexPage);
这篇关于如何在 _app.js 中使用 getStaticProps 在 Next.js 的每个页面中显示从 api 获取的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!