Next.js 13.4点赞按钮开发遇Maximum call stack size exceeded错误求助
Next.js 13.4 点赞按钮栈溢出错误解决
我是一名初级开发者,正在使用Next.js 13.4开发点赞按钮功能,希望点击按钮时实现点赞数递增,但出现如下错误:
Error: Maximum call stack size exceeded
相关代码如下:
"use client" import { formatDateString } from "@/lib/utils"; import Image from "next/image"; import Link from "next/link"; import { useEffect, useState } from "react"; import DeleteBuzzWeft from "../forms/DeleteBuzzWeft"; interface Props { id: string, currentUserId: string, parentId: string | null, content: string, author: { name: string; image: string; id: string; }, community: { id: string; name: string; image: string; } | null; createdAt: string; comments: { author: { image: string; } }[] isComment?: boolean; } const BuzzWeftCard = ({ id, currentUserId, parentId, content, author, community, createdAt, comments, isComment }: Props) => { const [ randomLikes, setRandomLikes] = useState(0); useEffect(() => { setRandomLikes(Math.floor(Math.random() * 1000)); }, []); return ( <article className={`flex w-full flex-col rounded-xl ${isComment ? 'px-0 xs:px-7' : 'bg-dark-2 p-7'}`}> <div className="flex items-start justify-between"> <div className="flex w-full flex-1 flex-row gap-4"> <div className="flex flex-col items-center"> <div className="buzz-card_bar" /> </div> <div className="flex w-full flex-col"> <p className="mt-2 text-small-regular text-light-1">{content}</p> <div className={`${isComment && 'mb-10'} mt-5 flex flex-col gap-3`}> <div className="flex gap-3.5"> <Link href={`/`}> <Image src='/assets/heart-gray.svg' alt="heart" width={24} height={24} className="cursor-pointer object-contain" /> </Link> {/* <div className=""> */} {/* <Link href={`/buzz/${id}`}> */} <Image src='/assets/reply.svg' alt="reply" width={24} height={24} className="cursor-pointer object-contain" /> <p className=" text-x-small-semibold">{randomLikes}</p> {/* </Link> */} {/* </div> */} </div> </div> </div> </div> </div> </article> ) } export default BuzzWeftCard
错误原因
出现栈溢出的核心原因是点赞按钮的点击事件处理逻辑错误,常见场景包括:
- 直接在
onClick中执行setRandomLikes(randomLikes + 1)而非包裹在函数内,导致组件渲染时立即调用setState触发重渲染,重渲染又再次执行setState,形成无限循环耗尽调用栈。 - 使用非函数式更新状态,闭包捕获旧状态值引发异常更新逻辑。
解决方案
- 定义点赞处理函数,使用函数式更新获取最新状态值,避免闭包问题:
const handleLike = () => { setRandomLikes(prevLikes => prevLikes + 1); }; - 修改点赞按钮代码,移除不必要的跳转
Link(若仅需点赞无需跳转),并绑定点击事件:<div onClick={handleLike} className="cursor-pointer"> <Image src='/assets/heart-gray.svg' alt="heart" width={24} height={24} className="object-contain" /> </div> - 当前代码中
useEffect为空依赖仅初始化点赞数,逻辑正确无需修改。
修改后的完整代码
"use client" import { formatDateString } from "@/lib/utils"; import Image from "next/image"; import Link from "next/link"; import { useEffect, useState } from "react"; import DeleteBuzzWeft from "../forms/DeleteBuzzWeft"; interface Props { id: string, currentUserId: string, parentId: string | null, content: string, author: { name: string; image: string; id: string; }, community: { id: string; name: string; image: string; } | null; createdAt: string; comments: { author: { image: string; } }[] isComment?: boolean; } const BuzzWeftCard = ({ id, currentUserId, parentId, content, author, community, createdAt, comments, isComment }: Props) => { const [ randomLikes, setRandomLikes] = useState(0); useEffect(() => { setRandomLikes(Math.floor(Math.random() * 1000)); }, []); // 点赞处理函数 const handleLike = () => { setRandomLikes(prevLikes => prevLikes + 1); }; return ( <article className={`flex w-full flex-col rounded-xl ${isComment ? 'px-0 xs:px-7' : 'bg-dark-2 p-7'}`}> <div className="flex items-start justify-between"> <div className="flex w-full flex-1 flex-row gap-4"> <div className="flex flex-col items-center"> <div className="buzz-card_bar" /> </div> <div className="flex w-full flex-col"> <p className="mt-2 text-small-regular text-light-1">{content}</p> <div className={`${isComment && 'mb-10'} mt-5 flex flex-col gap-3`}> <div className="flex gap-3.5 items-center"> {/* 移除跳转Link,改为点击点赞 */} <div onClick={handleLike} className="cursor-pointer"> <Image src='/assets/heart-gray.svg' alt="heart" width={24} height={24} className="object-contain" /> </div> <div className="cursor-pointer"> <Image src='/assets/reply.svg' alt="reply" width={24} height={24} className="object-contain" /> </div> <p className="text-x-small-semibold">{randomLikes}</p> </div> </div> </div> </div> </div> </article> ) } export default BuzzWeftCard
内容的提问来源于stack exchange,提问作者Anas Isah
相关产品推荐
相关产品推荐

