【问题标题】:How do I create show page based on id of item clicked如何根据单击的项目的 ID 创建显示页面
【发布时间】:2021-04-19 01:46:00
【问题描述】:

我正在创建通过 .map 函数循环的项目列表。我希望这些项目中的每一个都与其他一些细节一起呈现在一个页面中。

import React from 'react'
import {faArrowRight, faMusic, faPlay, faPlayCircle, faTachometerAlt} from "@fortawesome/free-solid-svg-icons";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import music  from '../mocks/music.json'
import { Link } from 'gatsby'
import Music from '../pages/music'

const newData = music.map( (data) => {
    return (
        <div className="row no-gutters justify-content-between align-items-center">
        <div className="col-auto">
            <button className="btn-gradient btn-circle">
                <FontAwesomeIcon icon={faPlayCircle} />
            </button>
        </div>
        <div className="col">
            <div className="music-list-content">
                <span className="artist">{data.author}</span>
                 <Link to={`/music/${data.id}`}>{data.title}</Link>
                 
                <span className="play">
                    <FontAwesomeIcon icon={faPlay} /> {data.duration}
                </span>
            </div>
        </div>
        <div className="col-auto">
            <span className="badge-dark badge">{data.genre}</span>
        </div>
    </div>
    )
})
const membersToRender = music.filter(member => member.id)
const numRows = membersToRender.length
const Musics = () => {
    return (
        <div>
            <div className="title">
                <h5>New Music</h5>
                <span>{numRows} new songs</span>
            </div>
            <div>
                <div className="music-list card-wrapper">
                    {newData}
                </div>
            </div>
            <div className="footer-wrapper">
                <div>
                    <FontAwesomeIcon icon={faMusic} />
                    <span>Song Library</span>
                </div>
                <FontAwesomeIcon icon={faArrowRight} />
            </div>
        </div>
    )
}

export default Musics

我创建了一个链接,每当我点击它时,它都会将我带到另一个页面(未找到页面),并附加了 id 和 .js 扩展名。

请问,怎么办?我想点击标题并将其显示在整页上。

【问题讨论】:

    标签: node.js json reactjs graphql gatsby


    【解决方案1】:

    您的逻辑看起来不错,但是,您错过了最重要的部分,即页面创建,因为您没有创建页面,所以您的所有链接都已损坏。

    在 Gatsby 中,您有两种不同的方式来创建页面:

    • 使用gatsby-node.js 动态创建页面:在处理大量数据时,例如您的 JSON,让 Gatsby 处理为 Gatsby 创建页面的责任会更容易。由于您是从 JSON 采购的,因此您需要将所有内容设置为 create dynamic pages.

      const path = require("path")
      
      // Implement the Gatsby API “createPages”. This is called once the
      // data layer is bootstrapped to let plugins create pages from data.
      exports.createPages = async ({ graphql, actions, reporter }) => {
         const { createPage } = actions
         const musics= require("./data/mocks/musics.json")
      
         const musicTemplate = path.resolve(`src/templates/music-template.js`)
      
         musics.forEach(music) => {
           createPage({
             path: `/music/${music.slug}`
             component: musicTemplate,
             context: {
               title: music.title,
               description: music.description,
               // and so on for the rest of the fields
             },
           })
         })
      }
      
      

      注意:我假设您的 JSON 已正确定义和格式化,包含我查询的所有字段。

      您的musicTemplate 必须是一个模板(在/templates 文件夹内)。

      请注意,您正在通过 Gatsby 的上下文传递一些字段,这意味着这些字段将通过模板中的 props.pageContext 可用。所以,在那里,创建一个模板,如:

          import React from "react"
          import Layout from "../components/layout"
      
         export default function MusicTemplate({pageContext}) {
            return (
              <Layout>
                <div>Hello musician {pageContext.title}</div>
              </Layout>
            )
          }
      
      

      因此,正如我所说,通过这种方法,您将基于 JSON 文件创建动态页面,它们将在 localhost:8000/music/{music.slug} 中可用,并且指向那里的所有参考和链接都是有效的。

      我还建议使用static query/useStaticQuery 在该循环中从您的 JSON 中检索数据。如果您从该数据创建一个静态查询(在一个单独的组件中),您将能够在您的项目中按需获取它,因此您将重用逻辑的一个有趣部分。最好使用它而不是直接请求 JSON。

      您可以关注this guide from the great Jason Lengstorf,这主要是您需要的。

    • /pages 文件夹中添加.js 文件:Gatsby 推断 /pages 文件夹的内部结构,并将根据该结构创建页面。例如,如果你有这样的结构:/pages/musicians/name1.js Gatsby 将创建一个类似localhost:8000/musicians/name1 的页面。

    如前所述,第一种方法符合您的要求,并且是此用例的首选,因为第二种方法的可扩展性和可维护性较差。

    【讨论】:

    • 嗨,谢谢... 请,我想知道我是否需要删除 .map 函数并替换为上面的代码,或者我只需要创建 Gatsby-node.js 并添加代码并为另一个创建一个模板文件。同时,我想要实现的是单击上面代码中显示的标题,然后打开一个单独的页面,其中包含针对具有相应 id 的特定项目的所有详细信息
    • 您需要删除您的代码并将其替换为我提供的代码。使用这种方法,您将在gatsby-node.js 中创建页面,并且在项目的任何页面中,您都可以链接到该创建的页面(例如/musician/payne)。在那里,您将列出该音乐家的所有信息,因为它已编码在模板组件中。
    • 我在代码中使用了第二种方法,一切正常。
    • 另外,使用第二种方法,我打算让它显示在当前页面(列表上方),它显示 pageContext.title undefined。
    • 当然,页面在提供之前没有上下文,只有在gatsby-node.js 中提供上下文才有效(第一种方法)
    【解决方案2】:

    您应该使用 React-Router (https://reactrouter.com/web/example/basic) 进行一些路由。

    所以链接必须指向交换机中的路由,就像链接示例中一样。

    【讨论】:

    • 如果您对此进行扩展并提供一个示例,这样您的问题就不会依赖于链接,这将是一个更好的答案。还有问题提到 gstsby 所以我认为最好使用 Link
    猜你喜欢
    • 1970-01-01
    • 2021-01-28
    • 1970-01-01
    • 1970-01-01
    • 2018-11-29
    • 1970-01-01
    • 2022-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多