Kaa*_*aan 6 menu reactjs next.js getstaticprops
我正在尝试创建一个菜单组件,在构建时读取 pages 文件夹的内容。但是,我没有任何成功。这是我尝试过的:
import path from "path";
import * as ChangeCase from "change-case";
export default class Nav extends React.Component {
render() {
return (
<nav>
{this.props.pages.map((page) => (
<a href={page.link}>{page.name}</a>
))}
</nav>
);
}
async getStaticProps() {
let files = fs.readdirSync("../pages");
files = files.filter((file) => {
if (file == "_app.js") return false;
const stat = fs.lstatSync(file);
return stat.isFile();
});
const pages = files.map((file) => {
if (file == "index.js") {
const name = "home";
const link = "/";
} else {
const link = path.parse(file).name;
const name = ChangeCase.camelCase(link);
}
console.log(link, name);
return {
name: name,
link: link,
};
});
return {
props: {
pages: pages,
},
};
}
}
Run Code Online (Sandbox Code Playgroud)
这不起作用,组件没有收到 pages 道具。我尝试切换到功能组件,从 返回承诺getStaticProps(),切换到getServerSideProps()并将目录读取代码包含到渲染方法中。
前两个不能工作,因为getStaticProps()和getServerSideProps()永远不会被执行,除非该组件是一个页面,其中包括在渲染,因为代码可能上不会有FS前端运行,因为FS是没有定义或导入的方法失败的代码使用权。
我还尝试将代码添加到getStaticProps()内部的函数中_app.js,希望通过上下文将页面推送到组件,但似乎getStaticProps()也没有在那里调用。
我可以在包含菜单的页面的 getStaticProps 函数中运行代码,但我必须对每个页面重复此操作。即使我将逻辑提取到从 getStaticProps 调用的模块中,也是如此:
// ...
export async function getStaticProps() {
return {
props: {
pages: MenuMaker.getPages(),
// ...
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后通过Layout组件将页面传递给页面内部的导航组件:
export default function Page(props) {
return (
<Layout pages={props.pages}></Layout>
)
}
Run Code Online (Sandbox Code Playgroud)
那么这仍然是很多样板要添加到网站上的每个页面。
肯定有更好的方法......不可能在构建时没有办法将静态数据添加到全局状态,是吗?如何在构建时生成动态菜单?
我设法通过从 next.config.js 导出一个函数并设置一个包含菜单结构的环境变量来使其工作。我将菜单加载代码抽象到它自己的文件中。看到结果后,我更明白为什么我找不到任何人做类似事情的例子:
菜单没有按照我想要的方式订购。我可以按字母顺序或按修改日期对其进行排序,但实际上几乎总是需要根据页面主题对其进行手动排序。我可以使用一个整数,或者附加到文件名或文件中的某个地方(可能在注释行中)。但回想起来,我认为在组件中对链接进行硬编码可能毕竟是最好的方法,因为它提供了更大的灵活性,并且即使从长远来看也可能不会有更多的工作。
话虽如此,我正在分享我的解决方案,因为它是一种初始化应用程序范围静态状态的方法。这并不理想,如果你想重新计算这里的变量,你将不得不重新启动开发服务器,这就是为什么我仍然对其他可能的解决方案感兴趣,但它确实有效。所以这里是:
下一个.config.js
const menu = require("./libraries/menu.js");
module.exports = (phase, { defaultConfig }) => {
return {
// ...
env: {
// ...
menu: menu.get('pages'),
// ...
},
// ...
};
};
Run Code Online (Sandbox Code Playgroud)
图书馆/menu.js
const fs = require("fs");
const path = require("path");
const ccase = require("change-case");
module.exports = {
get: (pagePath) => {
if (pagePath.slice(-1) != "/") pagePath += "/";
let files = fs.readdirSync(pagePath);
files = files.filter((file) => {
if (file == "_app.js") return false;
const stat = fs.lstatSync(pagePath + file);
return stat.isFile();
});
return files.map((file) => {
if (file == "index.js") {
return {
name: "Home";
link: "/";
};
} else {
link = path.parse(file).name;
return {
link: link;
name: ccase.capitalCase(link);
};
}
});
},
};
Run Code Online (Sandbox Code Playgroud)
然后从可以包含在布局中的组件中的环境变量生成实际菜单:
组件/导航.js
import Link from "next/link";
export default class Nav extends React.Component {
render() {
return (
<nav>
{process.env.menu.map((item) => (
<Link key={item.link} href={item.link}>
<a href={item.link}>
{item.name}
</a>
</Link>
))}
</nav>
);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2187 次 |
| 最近记录: |