我正在尝试创建一个菜单组件,该组件在构建时读取 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,
},
};
}
}
这不起作用,组件没有收到 pages 道具。我尝试过切换到一个功能组件,从 中返回一个 promise getStaticProps()
,切换到getServerSideProps()
,并将目录读取代码包含到 render 方法中。
前两个不起作用,因为除非组件是页面getStaticProps()
,getServerSideProps()
否则永远不会被调用,并且在 render 方法中包含代码失败,因为 fs 未定义或可导入,因为代码可能在没有 fs 的前端运行使用权。
我还尝试将代码添加到内部的getStaticProps()
函数中_app.js
,希望通过上下文将页面推送到组件,但似乎getStaticProps()
也没有在那里调用。
我可以在包含菜单的页面的 getStaticProps 函数中运行代码,但我必须对每个页面重复该操作。即使我将逻辑提取到从 getStaticProps 调用的模块中,也像:
// ...
export async function getStaticProps() {
return {
props: {
pages: MenuMaker.getPages(),
// ...
}
}
}
然后通过 Layout 组件将页面传递给页面内的导航组件:
export default function Page(props) {
return (
<Layout pages={props.pages}></Layout>
)
}
那么这仍然是很多样板要添加到网站上的每个页面。
肯定有更好的办法……不可能是没有办法在构建时给全局状态添加静态数据吧?如何在构建时生成动态菜单?