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

Next.js传递API响应Props给子组件时触发RangeError求助

Next.js传递API响应Props到子组件时触发栈溢出错误

我是Next.js新手,尝试将API调用返回的响应作为Props传递给子组件时,出现了RangeError: Maximum call stack size exceeded错误。静态传递数据时功能正常,但传递动态渲染的API响应数据时就会报错。

错误截图

错误截图

相关代码

page.jsx

import styles from './page.module.css';
import EmployeeDashboardNavbar from './serverComponents/EmployeeNavbar';
import EmployeeDashboardContent from './serverComponents/employeeDashboardContent';

const EmployeeDashboard = () => {
  return (
    <div className={styles["emp-dashboard-top"]}>
      <div className={styles["emp-dashboard-body"]}>
        <EmployeeDashboardNavbar />
        <EmployeeDashboardContent />
      </div>
    </div>
  );
};

export default EmployeeDashboard;

EmployeeDashboardContent.jsx

import { findTaskswithDeptAdmin } from "@/actions/taskActions";
import EmpCards from "../clientComponents/employeeCard";
import styles from "./server.module.css";
import EmployeeCalendar from "../clientComponents/calendar";

const EmployeeDashboardContent = async () => {
  const tasksOfUser = await findTaskswithDeptAdmin({
    empId: "652a39fbfd78c72ec09f26b5",
  });
  const filteredTasks = tasksOfUser.filter((tk) => tk.completionStatus === "Assigned")
  console.log(filteredTasks);

  return (
    <>
      <div className={styles["emp-dash-main"]}>
        <div style={{ width: "100%", display: "flex" }}>
          <div className={styles["emp-dash-main-left"]}>
            <div>
              <div>
                <div className={styles["emp-header-nav"]}>
                  <div className={styles["emp-header"]}>
                    <h3>Krish</h3>
                  </div>
                </div>
                <EmpCards />
              </div>
              <div className={styles["emp-body"]}>
                <div className={styles["emp-meeting-schedule"]}>
                  <button className={styles["emp-dashboard-add-employee"]}>
                    Meeting Details
                  </button>
                </div>
                <div>
                  <table className={styles["emp-dash"]}>
                    <thead>
                      <tr className={styles["emp-table-head"]}>
                        <th>Task</th>
                        <th>Head</th>
                        <th>Department</th>
                        <th>Date</th>
                      </tr>
                    </thead>
                    <tbody>
                      {tasksOfUser
                        .filter((tk) => tk.completionStatus === "Assigned")
                        .map((task) => (
                          <tr
                            className={styles["emp-dashboard-table-data"]}
                            key={task._id}
                          >
                            <td>{task.taskName}</td>
                            <td>{task.deptId.name}</td>
                            <td>{task.adminId.adminName}</td>
                            <td>{task.deadline}</td>
                          </tr>
                        ))}
                    </tbody>
                  </table>
                </div>
                <EmployeeCalendar tasks={filteredTasks}/>
              </div>
            </div>
          </div>
          <div className={styles["emp-dash-main-right"]}>hiii</div>
        </div>
      </div>
    </>
  );
};

export default EmployeeDashboardContent;

EmployeeCalendar.jsx

"use client";

import Calendar from "react-calendar";
import 'react-calendar/dist/Calendar.css';

import styles from "./client.module.css";

const EmployeeCalendar = ({tasks}) => {
  console.log(tasks)
  return (
    <>
      <div
        className={`${styles["emp-calender"]} ${styles["react-calender"]}`}
        style={{ display: "grid", placeItems: "center" }}
      >
        {/* <div>
          <h4 style={{ cursor: "pointer", color: "red" }}>Today</h4>
        </div> */}
        <Calendar />
      </div>
    </>
  );
};

export default EmployeeCalendar;

filteredTasks数据示例

[
  {
    taskName: 'task 3',
    adminId: {
      adminName: 'Krish',
      email: 'krish@gmail.com',
      password: '123',
      document: 'PAN',
      __v: 0
    },
    deptId: { name: 'HR', __v: 0 },
    deadline: '2023-10-21',
    status: false,
    completedDate: '',
    completionStatus: 'Assigned',
    createdAt: '2023-10-23T12:27:33.523Z',
    updatedAt: '2023-10-23T12:27:33.523Z',
    __v: 0
  }
]

静态传递数据时可以正常运行,但不明白为什么动态渲染的API响应数据传递时会出错。


问题原因与解决方案

这个错误的核心原因是Next.js在序列化服务器组件传递给客户端组件的Props时,遇到了无法处理的循环引用或非可序列化数据。API返回的filteredTasks里包含MongoDB文档对象(比如带__v字段的嵌套对象),这类对象可能隐含循环引用,或者包含无法被JSON序列化的属性,导致序列化过程陷入无限循环,最终触发栈溢出。

具体修复步骤:

  1. 序列化API响应数据:在服务器组件中,将API返回的任务数据转换为纯JSON对象,去除MongoDB文档的额外属性和潜在循环引用。
    修改EmployeeDashboardContent.jsx中的数据处理逻辑:

    const tasksOfUser = await findTaskswithDeptAdmin({
      empId: "652a39fbfd78c72ec09f26b5",
    });
    // 将MongoDB文档转为纯JSON对象
    const serializedTasks = JSON.parse(JSON.stringify(tasksOfUser));
    const filteredTasks = serializedTasks.filter((tk) => tk.completionStatus === "Assigned");
    

    这样处理后,数据会变成纯可序列化的JSON结构,消除循环引用和非标准属性。

  2. 仅传递必要数据:如果不需要所有字段,可以手动提取需要的属性,减少传递的数据量同时避免不必要的嵌套问题。比如:

    const filteredTasks = tasksOfUser
      .filter((tk) => tk.completionStatus === "Assigned")
      .map(task => ({
        taskName: task.taskName,
        deadline: task.deadline,
        // 只传递日历组件需要的字段
      }));
    
  3. 检查组件Props处理:后续若要在日历组件中使用tasks,确保组件不会因复杂数据结构触发额外的渲染循环。

验证逻辑

静态数据能正常运行,是因为静态数据本身就是纯JSON结构,没有MongoDB文档的额外属性和潜在循环引用,序列化过程不会出问题。而动态API返回的是MongoDB文档实例,必须先转为纯JSON才能安全传递给客户端组件。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 08:13:20