Gatsby模板GraphQL查询中如何引用变量获取当前查询的tag值
解决方案
核心思路:SSR/SSG场景下无需通过前端window对象获取参数,直接在服务端页面生成/渲染阶段,将路由中携带的标签值同时注入GraphQL查询变量和页面上下文,同时满足查询传参和前端展示需求。
- 如果你使用Gatsby框架,实现步骤如下:
- 在
gatsby-node.js的createPage逻辑中为每个标签生成独立页面,将标签值通过context参数传递
exports.createPages = async ({ graphql, actions }) => { const { createPage } = actions // 查询所有文章的标签 const tagRes = await graphql(` query { allMarkdownRemark { nodes { frontmatter { tags } } } } `) // 标签去重 const allTags = [...new Set(tagRes.data.allMarkdownRemark.nodes.flatMap(node => node.frontmatter.tags))] // 为每个标签生成页面 allTags.forEach(tag => { createPage({ path: `/tags/${tag}/`, // 可自定义路由规则 component: require.resolve("./src/templates/tag-result.js"), context: { // 此处传递的tag会自动作为变量注入到页面的GraphQL查询中 tag: tag } }) }) }
- 在标签结果模板中直接从
pageContext取标签值用于展示,原有查询无需修改
// src/templates/tag-result.js import * as React from "react" export default function TagResultPage({ data, pageContext }) { // 直接取上下文里的标签值展示 const currentTag = pageContext.tag const posts = data.allMarkdownRemark.nodes return ( <div> <h1>搜索标签为{currentTag}的结果</h1> {/* 此处渲染文章列表 */} </div> ) } // 原有GraphQL查询无需修改,变量会自动注入 export const Search = graphql` query SearchResults($tag: String = "") { allMarkdownRemark(filter: { frontmatter: { tags: { in: [$tag] } } }) { nodes { frontmatter { title date } } } } `
- 如果你使用Next.js框架,实现步骤如下:
直接在getServerSideProps中获取路由参数,同时传给GraphQL查询和页面props即可:
// pages/tags/[tag].js 动态路由文件 import * as React from "react" export async function getServerSideProps(context) { // 从路由参数中取标签值 const currentTag = context.params.tag // 执行GraphQL查询,传入标签变量 const queryRes = await fetch("你的GraphQL接口地址", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ query: ` query SearchResults($tag: String = "") { allMarkdownRemark(filter: { frontmatter: { tags: { in: [$tag] } } }) { nodes { frontmatter { title date } } } } `, variables: { tag: currentTag } }) }) const { data } = await queryRes.json() return { props: { currentTag, posts: data.allMarkdownRemark.nodes } } } export default function TagResultPage({ currentTag, posts }) { return ( <div> <h1>搜索标签为{currentTag}的结果</h1> {/* 此处渲染文章列表 */} </div> ) }
内容的提问来源于stack exchange,提问作者Ryan
相关产品推荐
相关产品推荐

