Issue
I am trying to build a component similar to how Twitter displays a tweet in Next.js13, and once clicked, will lead to the Post-Page of that tweet: /[username]/status/[tweet_id]
. I want it to invoke the Link ONLY when you click the post itself, not when you click with any of the buttons or the content within the tweet (unless the content that is clicked is text).
My problem:
I could get the redirect working, but for some reason when you click any of the buttons or the content within the component, it still redirects you.
What I'm trying to mimic:
Here is an example of how Twitter reacts when clicking a button within the tweet vs clicking on the post itself:
Clicking the Like button doesn't redirect but clicking the post itself does. This is what I'm trying to go for.
My code:
import InteractionComponent from "./InteractionComponent";
import { BsDot, BsThreeDots } from "react-icons/bs";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import Link from "next/link";
import type { Tweet } from "@/lib/types/tweet.types";
import type { UserData } from "@/lib/types/userdata.types";
dayjs.extend(relativeTime);
export default async function PostComponent(props: { tweet: Tweet, userData: UserData }) {
const { tweet, userData } = props;
return (
<div className="flex flex-col cursor-pointer hover:bg-slate/5">
<Link href="/">
<div className="flex flex-row border-b-2 p-4 border-slate/25">
<div className="mr-3">
<div className="h-[40px] w-[40px] bg-slate rounded-full"></div>
</div>
<div className="flex flex-col w-full">
<div className="flex flex-row justify-between w-full">
<div className="flex flex-row text-sm justify-between">
<span className="font-bold">{tweet.authorInfo.authorDisplayName}</span>
<div className="flex flex-row ml-2 font-light">
<span className="text-slate/75">@{tweet.authorInfo.authorUserName}</span>
<BsDot className="h-full text-slate/75" />
<span className="text-slate/75">{dayjs(tweet.createdAt).fromNow()}</span>
</div>
</div>
<div>
<BsThreeDots className="h-full text-slate/75" />
</div>
</div>
<div id="post" className="text-sm font-light mb-2">
<span>{tweet.textContent}</span>
</div>
<div className="flex flex-row text-slate/75 text-lg mt-2 justify-between w-full z-10">
<InteractionComponent tweet={tweet} userData={userData} />
</div>
</div>
</div>
</Link>
</div>
)
}
What I already tried:
I tried moving the <Link>
component around but it doesn't seem to do the trick. I even tried to use a position: absolute
on the div for the <InteractionComponent />
to see if I can somehow move past the Link (as a last ditch effort) but that didn't do the trick either... I even tried to google this issue but I don't even know exactly what to google to find the solution. Any help is appreciated, thank you so much!
Solution
This issue is probably happening because of Event Propagation. There is two-point solution to your issue which I can surmise.
<Link>
component is wrapping the entire tweet component, including the buttons and content which you can modify to only wrap author info and tweet content.- Stop the propagation when a button is clicked.
Something like:
import InteractionComponent from "./InteractionComponent";
import { BsDot, BsThreeDots } from "react-icons/bs";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import Link from "next/link";
import { Tweet } from "@/lib/types/tweet.types";
import { UserData } from "@/lib/types/userdata.types";
dayjs.extend(relativeTime);
export default function PostComponent(props: { tweet: Tweet, userData: UserData }) {
const { tweet, userData } = props;
const handleClick = (e) => {
e.stopPropagation();
};
return (
<div className="flex flex-col cursor-pointer hover:bg-slate/5">
<div className="flex flex-row border-b-2 p-4 border-slate/25">
<div className="mr-3">
<div className="h-[40px] w-[40px] bg-slate rounded-full"></div>
</div>
<div className="flex flex-col w-full">
<div className="flex flex-row justify-between w-full">
<Link href="/">
<div className="flex flex-row text-sm justify-between cursor-pointer">
<span className="font-bold">{tweet.authorInfo.authorDisplayName}</span>
<div className="flex flex-row ml-2 font-light">
<span className="text-slate/75">@{tweet.authorInfo.authorUserName}</span>
<BsDot className="h-full text-slate/75" />
<span className="text-slate/75">{dayjs(tweet.createdAt).fromNow()}</span>
</div>
</div>
</Link>
<div>
<BsThreeDots className="h-full text-slate/75" />
</div>
</div>
<Link href="/">
<div id="post" className="text-sm font-light mb-2 cursor-pointer">
<span>{tweet.textContent}</span>
</div>
</Link> {/* NOTICE THIS */}
<div className="flex flex-row text-slate/75 text-lg mt-2 justify-between w-full z-10">
<InteractionComponent tweet={tweet} userData={userData} onClick={handleClick} /> {/* onClick applied HERE */}
</div>
</div>
</div>
</div>
);
}
NOTE: You need to change the prop requirement for InteractionComponent
to handle the onClick
prop as needed.
Answered By - mandy8055
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.