【问题标题】:How can I generate a separate NextJS page for each FaunaDB Document?如何为每个 FaunaDB 文档生成单独的 NextJS 页面?
【发布时间】:2022-01-26 00:51:17
【问题描述】:

如何在子目录中的每个页面上生成不同的标题?

我的代码没有抛出任何错误,但不幸的是,Title 组件在它应该呈现的每个页面上呈现 every title-item,例如每个app.com/title/<title> 都会呈现 same 视图(标题列表)。我认为 getStaticPaths 参数化正确,但我不认为 getStaticProps 是。

export default function Title({ paper }) {

    // paper is just the entire dataset, and isn't split by id or author etc.

    return (
            <div>
                {paper.map(paper => (
                        <h1>{paper.data.title}</h1>
                ))}
            </div>
    )
}

export async function getStaticProps({ params }) {

    // ideally, results should be split down to e.g. `/api/getPapers/title`, but this didn't work

    const results = await fetch(`http://localhost:3000/api/getPapers/`).then(res => res.json());

    return {
        props: {
            paper: results
        }
    }
}

export async function getStaticPaths() {
    const papers = await fetch('http://localhost:3000/api/getPapers').then(res => res.json());

    const paths = papers.map(paper => {
        return {
            params: {
                authors: paper.data.title.toLowerCase().replace(/ /g, '-')
            }
        }
    })

    return {
        paths,
        fallback: false
    }
}

这是getPapers API 函数。

const faunadb = require("faunadb");

// your secret hash
const secret = process.env.FAUNADB_SECRET_KEY;
const q = faunadb.query;
const client = new faunadb.Client({ secret });

module.exports = async (req, res) => {
  try {
    const dbs = await client.query(
      q.Map(
        // iterate each item in result
        q.Paginate(
          // make paginatable
          q.Match(
            // query index
            q.Index("all_research_papers") // specify source
          )
        ),
        (ref) => q.Get(ref) // lookup each result by its reference
      )
    );
    // ok
    res.status(200).json(dbs.data);
  } catch (e) {
    // something went wrong
    res.status(500).json({ error: e.message });
  }
};

【问题讨论】:

  • 您是否创建了一个 API 路径来按标题从 FaunaDB 检索一篇论文?我想这就是你在这种情况下所需要的。另外,您不应该从getStaticProps 的内部API 路由中获取数据,直接使用逻辑即可。
  • 我的 API 路由在一个批次中生成所有文档。是否有任何按参数获取文档的文档示例(即按标题的论文)?
  • 可以分享一下getPapers API 函数吗? papers 可能是几件事,具体取决于您如何从 Fauna 返回结果。
  • @ptpaterson,我已经包含了上面的 API 函数。
  • @WΔ_,我已经根据API函数更新了答案

标签: javascript reactjs next.js faunadb


【解决方案1】:

我为每个文档呈现单独页面的尝试缺少 dynamic API 调用。我只是希望通过 single(批处理文档)API 调用来呈现动态页面。

这是一个典型的动态 API 路由,称为[index.js]

const faunadb = require('faunadb')

// your secret hash
const secret = process.env.FAUNADB_SECRET_KEY
const q = faunadb.query
const client = new faunadb.Client({ secret })

export default async (req, res) => {
  const {
    query: { index },
  } = req;

  try {
    const papers = await client.query(
      q.Get(q.Ref(q.Collection('<name of the collection>'), index))
    );
    res.status(200).json(papers.data);
  } catch (e) {
    res.status(500).json({ error: e.message });
  }
};


一旦您的数据被动态检索,您就可以设置动态 page 路由,例如[id].js,使用useSWR 获取数据。

const { data, error } = useSWR(`/api/getPapers/${id}`, fetcher);

这是一个示例提取函数:

const fetcher = (url) => fetch(url).then((r) => r.json());

就我而言,然后我可以使用调用 {data.&lt;field&gt;} 检索任何给定字段。

【讨论】:

    【解决方案2】:

    您在 Path 对象中返回 authors。您需要确保您的页面文件命名为包含authors。例如:

    app_directory
    |- pages
      |- home.js
      |- title
        |- [authors].js
    

    也许你在params 对象中说authors,你的意思是title。在这种情况下,重命名params 对象和页面文件名。

        const paths = papers.map(paper => {
            return {
                params: {
                    title: paper.data.title.toLowerCase().replace(/ /g, '-')
                }
            }
        })
    
    app_directory
    |- pages
      |- home.js
      |- title
        |- [title].js
    

    这是getStaticPaths() 的文档。 https://nextjs.org/docs/basic-features/data-fetching#getstaticpaths-static-generation

    编辑:

    由于您的 API 函数从您的查询返回页面,结果的形状可能是

    {
      before: [/* before cursor */],
      after: [/* after cursor */],
      data: [
        { /* paper Document */ },
        { /* paper Document */ },
        { /* paper Document */ },
      ]
    }
    

    在这种情况下,您的代码需要映射到 papers.data 而不是 papers 本身。

        const paths = papers.data // select the data
          .map(paper => {
            return {
                params: {
                    title: paper.data.title.toLowerCase().replace(/ /g, '-')
                }
            }
        })
    

    【讨论】:

      猜你喜欢
      • 2021-07-17
      • 2020-07-12
      • 2017-09-07
      • 2020-10-11
      • 1970-01-01
      • 2021-12-05
      • 1970-01-01
      • 1970-01-01
      • 2011-11-17
      相关资源
      最近更新 更多