You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Hygraph博客超链接不显示问题求助(附代码)

问题:博客内容中超链接无法显示

我跟着YouTube上JavaScript Mastery的教程《Build and Deploy THE BEST Modern Blog App with React | GraphQL, NextJS, Tailwind CSS》开发博客,目前遇到博客内容里的超链接无法显示的问题。经排查确认问题出在前端,大概率位于以下PostDetail组件代码中。我尝试实现超链接的代码已注释但仍无法正常工作,联系Hygraph后也确定是前端问题,但无法定位具体原因。

import React from "react";
import moment from "moment";

const PostDetail = ({ post }) => {
  const getContentFragment = (index, text, obj, type) => {
    let modifiedText = text;

    if (obj) {
      if (obj.bold) {
        modifiedText = <b key={index}>{text}</b>;
      }

      if (obj.italic) {
        modifiedText = <em key={index}>{text}</em>;
      }

      if (obj.underline) {
        modifiedText = <u key={index}>{text}</u>;
      }

      // if (obj.link) {
      //   modifiedText = <a href={index}>{text}</a>;
      // }
    }

    switch (type) {
      case "heading-three":
        return (
          <h3 key={index} className="text-xl font-semibold mb-4">
            {modifiedText.map((item, i) => (
              <React.Fragment key={i}>{item}</React.Fragment>
            ))}
          </h3>
        );
      case "paragraph":
        return (
          <p key={index} className="mb-8">
            {modifiedText.map((item, i) => (
              <React.Fragment key={i}>{item}</React.Fragment>
            ))}
          </p>
        );
      case "heading-four":
        return (
          <h4 key={index} className="text-md font-semibold mb-4">
            {modifiedText.map((item, i) => (
              <React.Fragment key={i}>{item}</React.Fragment>
            ))}
          </h4>
        );
      case "image":
        return (
          <img
            key={index}
            alt={obj.title}
            height={obj.height}
            width={obj.width}
            src={obj.src}
          />
        );
      // case "link":
      //   return (
      //     <a href={index} className="text-md mb-4">
      //       {modifiedText.map((item, i) => (
      //         <React.Fragment key={i}>"{item}"</React.Fragment>
      //       ))}
      //     </a>
      //   );
      default:
        return modifiedText;
    }
  };

  return (
    <>
      <div className="bg-white shadow-lg rounded-lg lg:p-8 pb-12 mb-8">
        <div className="relative overflow-hidden shadow-md mb-6">
          <img
            src={post.featuredImage.url}
            alt=""
            className="object-top h-full w-full object-cover  shadow-lg rounded-t-lg lg:rounded-lg"
          />
        </div>
        <div className="px-4 lg:px-0">
          <div className="flex items-center mb-8 w-full">
            <div className="hidden md:flex items-center justify-center lg:mb-0 lg:w-auto mr-8 items-center">
              <img
                alt={post.author.name}
                height={30}
                width={30}
                className="align-middle rounded-full"
                src={post.author.photo.url}
              />
              <p className="inline align-middle text-gray-700 ml-2 font-medium text-lg">
                {post.author.name}
              </p>
            </div>
            <div className="font-medium text-gray-700">
              <svg
                xmlns="http://www.w3.org/2000/svg"
                className="h-6 w-6 inline mr-2 text-pink-500"
                fill="none"
                viewBox="0 0 24 24"
                stroke="currentColor"
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth="2"
                  d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
                />
              </svg>
              <span className="align-middle">
                {moment(post.createdAt).format("MMM DD, YYYY")}
              </span>
            </div>
          </div>
          <h1 className="mb-8 text-3xl font-semibold">{post.title}</h1>
          {post.content.raw.children.map((typeObj, index) => {
            const children = typeObj.children.map((item, itemindex) =>
              getContentFragment(itemindex, item.text, item)
            );

            return getContentFragment(index, children, typeObj, typeObj.type);
          })}
        </div>
      </div>
    </>
  );
};

export default PostDetail;

问题分析与修复方案

你的代码里处理超链接的逻辑存在3个关键错误:

  1. href取值错误:注释的代码中用index作为链接地址,这完全不符合逻辑,应该取Hygraph返回的链接字段(通常是obj.link)。
  2. 处理位置错误:Hygraph富文本中的超链接是文本节点的样式标记(和加粗、斜体同级),不是独立的块级节点,所以应该在处理文本样式的if分支里处理,而非switch的case分支。
  3. 核心逻辑被注释:你把处理链接的代码注释掉了,自然无法渲染超链接。

修复后的代码修改

取消注释链接处理逻辑,修正href取值,并添加基础样式:

const getContentFragment = (index, text, obj, type) => {
  let modifiedText = text;

  if (obj) {
    if (obj.bold) {
      modifiedText = <b key={index}>{text}</b>;
    }

    if (obj.italic) {
      modifiedText = <em key={index}>{text}</em>;
    }

    if (obj.underline) {
      modifiedText = <u key={index}>{text}</u>;
    }

    // 修复链接逻辑:使用正确的链接字段,添加样式
    if (obj.link) {
      modifiedText = <a href={obj.link} key={index} className="text-blue-600 underline hover:text-blue-800">{text}</a>;
    }
  }

  // 保留原switch逻辑,无需添加case "link"
  switch (type) {
    // ... 原case代码不变
    default:
      return modifiedText;
  }
};

额外注意事项

  • 若Hygraph返回的链接字段不是obj.link,可以在控制台打印item(即函数中的obj参数)查看具体字段名,比如obj.href或obj.url,对应修改即可。
  • 示例中添加了Tailwind样式让链接更显眼,你可以根据项目设计调整样式。

内容的提问来源于stack exchange,提问作者LoneScavengah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 14:25:42