Trying to implement hyperlinks in React, Hygraph blog

178 views Asked by At

Following JavaScript Mastery tutorial on YouTube: 'Build and Deploy THE BEST Modern Blog App with React | GraphQL, NextJS, Tailwind CSS'. Having trouble with hyperlinks not showing on my blog. I'm sure it's a problem on my end, and I'm sure it's in this file. I've commented out the code, that doesn't work proper:

    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;
    

I've tried to contact Hygraph, where we figured it's a problem on my front end. But I can't seem to understand, what I don't understand.

2

There are 2 answers

0
LoneScavengah On

Ended up taking a different approach with @graphcms/rich-text-react-renderer, changing PostDetail.jsx to this:

import React from "react";
import moment from "moment";
import { RichText } from "@graphcms/rich-text-react-renderer";

const PostDetail = ({ post }) => {
  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="30px"
                width="30px"
                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>

          <div className="mb-8">
            {post.excerpt && (
              <p
                className="text-gray-700 text-center text-lg
              font-normal px-4 lg:px-20 mb-8"
              ></p>
            )}
            <RichText content={post.content.raw.children} />
          </div>
        </div>
      </div>
    </>
  );
};

export default PostDetail;

You might run into a problem in Hygraph, where you can't put extra line breaks in your posts. Simply press shift + enter (instead of just enter).

0
Andrew Jones On

I followed the same tutorial and had the exact same question as you! I followed the suggestions you previously received of doing console.log for all of the variables that are passed to getContentFragment. By doing so, I found that I needed to check that obj.type equaled "link" and if it does, then return the modified text like this:

if (obj.type == 'link') {
    modifiedText = (<a href={obj.href}>Your text here</a>);
  }

If you would like the link to be replaced by the optional link text from hygraph, use the following:

if (obj.type == 'link') {
    modifiedText = (<a href={obj.href}>{obj['children'][0]['text']}</a>);
  }