NextJS出现Maximum call stack size exceeded错误,求解决及实现点赞功能
修复NextJS点赞/取消点赞功能的RangeError及逻辑问题
问题分析
出现RangeError: Maximum call stack size exceeded通常是因为无限循环渲染或对象循环引用。结合你的代码,核心问题包括:
- 点赞/取消点赞逻辑颠倒:点击"Liked"按钮时固定传
true,导致重复添加用户ID,无法触发取消操作 - 未根据当前点赞状态动态切换按钮UI与处理逻辑
- 可能因API响应存在循环引用,导致
JSON.parse或console.log时触发栈溢出
修复步骤
1. 动态判断用户点赞状态
在组件内实时计算当前用户是否已点赞,替代固定传参:
const hasLiked = likesArr.includes(user);
2. 修正handleLike逻辑
根据hasLiked状态决定操作类型,同时使用函数式更新确保状态基于最新值:
- 已点赞时:调用接口取消点赞,从数组移除用户ID
- 未点赞时:调用接口添加点赞,向数组添加用户ID
3. 避免循环引用问题
确保API返回的响应无循环引用,或简化响应日志输出(仅打印关键状态,而非整个响应对象)
4. 动态切换按钮UI
根据hasLiked状态自动切换图标和文字(已点赞/未点赞)
完整修复代码
'use client' import { useState } from "react"; import { FaRegComment } from "react-icons/fa"; import { PiShareFatThin } from "react-icons/pi"; import { AiOutlineLike, AiFillLike } from "react-icons/ai"; const PostReactions = ({ postReactions = [], postComments = [], postShares = [] }) => { const [user, setUser] = useState('66236aac5820fcac4e235f0c'); // 从props初始化点赞数组:提取已点赞用户ID const [likesArr, setLikesArr] = useState(postReactions.map(reaction => reaction.createdBy)); // 判断当前用户是否已点赞 const hasLiked = likesArr.includes(user); const handleLike = async () => { const postId = '663f2de2d1bbf549ac7fbabe'; const shouldAddLike = { postId, userId: user, likeType: 'like', isReacted: !hasLiked, // 反转当前状态:未点赞则添加,已点赞则取消 }; try { const response = await fetch(`/api/like`, { headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, method: "POST", body: JSON.stringify(shouldAddLike), }); const parse = await response.json(); // 简化日志输出,避免循环引用导致栈溢出 console.log('点赞操作结果:', parse.success ? '成功' : '失败'); // 函数式更新确保状态基于最新值 setLikesArr(prevArr => { if (hasLiked) { return prevArr.filter(id => id !== user); } else { return [...prevArr, user]; } }); } catch (error) { console.error("更新点赞状态失败:", error); } } return ( <div className="w-full md:w-2/3 flex-between py-2 font-poppins "> <div className="flex-center space-x-1 md:space-x-2 cursor-pointer" onClick={handleLike}> {/* 根据点赞状态切换图标 */} {hasLiked ? <AiFillLike className={`w-5 h-5`} /> : <AiOutlineLike className={`w-5 h-5`} />} {/* 根据点赞状态切换文字 */} <p className="base-semibold">{hasLiked ? 'Liked' : 'Like'}</p> </div> <div className="flex-center space-x-1 md:space-x-2 cursor-pointer"> <FaRegComment className={`w-5 h-5`} /> <p className="base-semibold">Comment</p> </div> <div className="flex-center space-x-1 md:space-x-2 cursor-pointer"> <PiShareFatThin className={`w-5 h-5`} /> <p className="base-semibold">Share</p> </div> </div> ); } export default PostReactions;
额外注意事项
- 确保
/api/like接口正确处理isReacted参数:true执行添加点赞,false执行取消点赞 - 若API返回的响应对象存在循环引用,需在后端序列化时排除循环字段,或前端仅打印必要状态字段
- 函数式更新(
setLikesArr(prevArr => ...))可避免闭包导致的状态更新滞后问题
内容的提问来源于stack exchange,提问作者khalidkakar
相关产品推荐
相关产品推荐

