昨天我們完成了 Slug 的添加跟靜態資料的讀取,今天我們要建立一個頁面模板來動態的創建頁面,話不多說,就直接來進入主題吧!
昨天我們已經在 gatsby-node.js 中新增不少程式碼,我們今天就接續著往下新增,我們先命名一個變數 basePath 並 assign 根目錄作為它的 value,接著我們使用 createPages 來建立頁面。
這邊要注意一下,我們元件還沒有新增,只是先暫時設一個路徑,因為我們要先嘗試 Query 資料,並對資料做一些處理,同樣的,我們也要對 Query 失敗來做些處理。
exports.createPages = async ({ actions, graphql, reporter }) => {
const basePath = "/"
actions.createPage({
path: basePath,
component: require.resolve("./src/templates/events.js"),
})
}
首先,我們要先查詢所有的資料,並且我們設定按照開始的日期去做排序,如果有出現錯誤的話,我們就直接處理掉它。
const result = await graphql(`
query {
allEvent(sort: { fields: startDate, order: ASC }) {
nodes {
id
slug
}
}
}
`)
if (result.errors) {
reporter.panic("error loading events", result.errors)
return
}
接著,我們將查詢到的資料來跑迴圈,最後利用 createPage 函式來創建頁面。
最後,我們要把剛剛先設定路徑的元件來補齊,所以我們在 gatsby-theme-events 工作區內 新增一個 src 資料夾,並在資料夾內再新增一個 templates 資料夾,然後在裡面放一個 events.js。
這時,你的資料夾結構應該會長得如下圖一樣。
再來我們快速的建立一個簡單的元件,所以我們將以下程式碼放入 events.js 中
import React from 'react'
const EventTemplate = () => {
return (
<p>TODO: Build the event page template</p>
)
}
export default EventTemplate
完成後,我們來測試一下頁面是否有成功的被建立起來,我們運行下面的指令來開啟開發伺服器
yarn workspace gatsby-theme-events develop
我們輸入 http://localhost:8000/404 來連結到 Gatsby 提供的 404 畫面,來看畫面是否有成功創建,現在畫面上面應該會有首頁加上你 data 內的資料筆數,例如下圖紅框處所示,讀者們可以試著點擊看看,是否能成功連到對應頁面。
而如果我們要在元件本身顯示數據的話,我們還需要用到 useStaticQuery 來幫助我們做 Query,所以我們要在 events.js 中先引入 graphql 與 useStaticQuery,接著在元件內執行我們要的 Query,你的程式碼應該會如下
接著,我們在 Gatsby-theme-events 工作區下的 src 資料夾內建立一個資料夾,名稱為 components 並在其中再建立一支 layout.js。
Layout 裡面我們接受上層傳來的 props 並解構其中的 children
import React from 'react'
const Layout = ({children}) => {
return (
<div>
<h1> ITHelp Gatsby Custom Theme</h1>
{children}
</div>
)
}
export default Layout
現在,我們還需要一個 list 頁面,所以同樣的,我們在 components 資料夾下再建立一支 event-list.js,裡面也是接受 props 傳來的值並解構出來做使用。
import React from 'react'
const EventList = ({events}) => {
return (
<pre>{JSON.stringify(events, null, 2)}</pre>
)
}
export default EventList
完成以上兩個通用元件後,我們將其引入至 templates 的 events.js 中,
import Layout from "../components/Layout"
import EventList from "../components/EventList"
接著,我們在 return 的 JSX 中調整成我們剛剛做好的元件
<Layout>
<EventList events={events} />
</Layout>
最後,我們重啟開發伺服器來看看吧!
讀者們應該能成功地看到剛剛我們在 Layout 中打的標題與子元件 EventList 接到 Props 傳來的值。
但我們可不能就這樣呈現給使用者觀看,所以我們要來調整一下 List 的 HTML 結構,來讓我們能將查詢出來的值放到對應的位置當中。
首先我們需要對 events 來跑迴圈,建立多個 tag li,並給他一個屬性為 key,key 裡面我們會放入獨一無二的值,也就是我們的 ID,接著,我們要給這些活動連結,而網址恰好就是我們之前塞入的 Slug,連結名稱就是 name,最後我們再對時間做一些處理後,即可回到我們的瀏覽器看看結果囉!
import React from "react"
import { Link } from "gatsby"
const EventList = ({ events }) => (
<>
<h2>Upcoming Events</h2>
<ul>
{events.map(event => (
<li key={event.id}>
<strong>
<Link to={event.slug}>{event.name}</Link>
</strong>
<br />
{new Date(event.startDate).toLocaleDateString("en-US", {
month: "long",
day: "numeric",
year: "numeric",
})}{" "}
in {event.location}
</li>
))}
</ul>
</>
)
export default EventList
讀者們如果看到如下圖一般,代表說已經改寫成功啦,我們成功地把資料一一都放到頁面上囉
但細心的讀者,會發現,奇怪,怎麼點連結下去還是一樣的畫面?
沒錯,我們今天的尾聲就是要再來創立內頁模板,
所以我們先在 components 與 templates 底下新增一個 Event.js,
首先,我們先來看 Templates 底下的 Event.js,裡頭我們會用 ID 來 Query 單篇文章的資料,且由於是頁面,所以我們可以直接用 graphql 來進行查詢。
查詢完畢後,我們會將查詢到的資料,利用 Props 與解構賦值的方式來傳遞給 components 裡的 Event.js,所以我們 templates/event.js 的程式碼會長得如下面這般
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
import Event from "../components/event"
export const query = graphql`
query($eventID: String!) {
event(id: { eq: $eventID }) {
name
url
startDate(formatString: "MMMM DD YYYY")
endDate(formatString: "MMMM DD YYYY")
location
slug
}
}
`
const EventTemplate = ({ data: { event } }) => (
<Layout>
<Event {...event} />
</Layout>
)
export default EventTemplate
而在 components/event.js 中,我們會接由上層傳下來的 Props 作為資料
import React from 'react'
const Event = ({ name, location, url, startDate, endDate }) => (
<div>
<h2>
{name} ({location})
</h2>
<p>
{startDate}-{endDate}
</p>
<p>
網址: <a href={url}>{url}</a>
</p>
</div>
)
export default Event
完成後,同樣的我們重啟開發伺服器來看看吧!
這時讀者們應該都能順利進到內頁當中了!
今天大家都順利的將資料轉成列表頁、內頁,
而明天我們要來為主題增加一些樣式,希望能在兩章以內結束建立自己主題的篇章。