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

Next.js项目中TypeError: Cannot read properties of undefined (reading 'Link')错误排查求助

我正在开发一个Next.js项目,逻辑是如果用户浏览器本地存储里有profile信息,就创建一个唯一ID并跳转到对应的聊天室链接,但一直遇到错误,试过各种方法包括问ChatGPT都没解决,希望大家帮忙看看。

相关代码

create-profile/page.tsx

"use client";

import Setup from "@/components/Setup";
import { useRouter } from "next/navigation";
import { useEffect } from "react";
import createUniqueLinkId from "@/libs/createlink";

const Page = () => {
  const router = useRouter();

  interface Profile {
    userName: string;
    avatar: number;
  }

  useEffect(() => {
    const profileFromLocalStorage = localStorage.getItem("profile");
    const profile: Profile | null = profileFromLocalStorage
      ? (JSON.parse(profileFromLocalStorage) as Profile)
      : null;

    const redirectOrSetup = async () => {
      if (profile) {
        try {
          const chatRoomLink = await createUniqueLinkId();
          router.push(`/chatroom/${chatRoomLink}`);
        } catch (error) {
          console.error("Failed to create chat room link", error);
        }
      }
    };

    redirectOrSetup();
  }, []);


  return (
    <div className="lg:mt-32 mt-8">
      <Setup />
    </div>
  );
};

export default Page;
import { v4 as uuidv4 } from "uuid";
import Link from "@/model/link";
import mongoose from "mongoose";
import { connectToDB } from "@/utils/database"; 

export const createUniqueLinkId = async (): Promise<string> => {
  let linkId = "";
  let isUnique = false;

  try {
    await connectToDB();
    console.log(Link)

    while (!isUnique) {
      linkId = uuidv4();
      
      const existingLink = await Link.findOne({ linkId });

      if (!existingLink) {
        isUnique = true;
      }
    }

    const newLink = new Link({ linkId });
    await newLink.save();

    return linkId;
  } catch (error) {
    console.error("Error creating unique link ID:", error);
    throw new Error("Failed to create a unique link ID");
  }
};

export default createUniqueLinkId;

link模型代码

import mongoose, { Document, Model, Schema } from 'mongoose';

export interface ILink extends Document {
  linkId: string,
  participants: string[];
  createdAt: Date;
}

const linkSchema = new Schema<ILink>({
  linkId:{
    type: String,
    required: true,
    unique: true,
  },
  participants: {
    type: [String],
    default: [],
  },
  createdAt: {
    type: Date,
    default: Date.now,
  },
}, { timestamps: true });

const Link: Model<ILink> = mongoose.models.Link || mongoose.model<ILink>('Link', linkSchema);

export default Link;

MongoDB连接代码

"use server"
import mongoose from "mongoose";

let isConnected: boolean = false;

// Connect to MongoDB
export const connectToDB = async (): Promise<void> => {
     
    if (isConnected) {
        console.log('MongoDB is already connected');
        return;  
    }

    try {
        await mongoose.connect(process.env.MONGODB_URI as string, {
            dbName: "anonymous_project"
        });

        isConnected = true;
        console.log('MongoDB connection is successful');
    } catch (error) {
        if (error instanceof Error) {
            throw new Error(`MongoDB connection failed: ${error.message}`);
        } else {
            throw new Error('MongoDB connection failed with an unknown error');
        }
    }
};

问题分析与解决方案

核心问题

从错误TypeError: Cannot read properties of undefined (reading 'Link')和代码结构来看,问题出在客户端组件直接执行了服务端专属的数据库操作:

  1. 你的page.tsx是标记"use client"的客户端组件,在浏览器环境运行,但它直接调用了createUniqueLinkId函数
  2. 这个函数依赖mongoose操作MongoDB,而mongoose是服务端库,浏览器环境中既没有初始化mongoose,也不允许直接连接数据库,所以mongoose.models是undefined,访问mongoose.models.Link就会抛出上述错误
  3. 另外,标记"use server"的connectToDB函数也不能在客户端环境被调用

修复方案:将数据库操作移到服务端执行

所有涉及数据库的逻辑必须放在服务端运行,我们可以通过Server Action或API路由来实现:

方案1:使用Next.js Server Action(推荐,App Router适配)

  1. 改造createlink.ts,添加"use server"标记,将其转为Server Action:
"use server"; // 标记为服务端执行的函数
import { v4 as uuidv4 } from "uuid";
import Link from "@/model/link";
import mongoose from "mongoose";
import { connectToDB } from "@/utils/database"; 

export const createUniqueLinkId = async (): Promise<string> => {
  let linkId = "";
  let isUnique = false;

  try {
    await connectToDB();

    while (!isUnique) {
      linkId = uuidv4();
      const existingLink = await Link.findOne({ linkId });
      if (!existingLink) {
        isUnique = true;
      }
    }

    const newLink = new Link({ linkId });
    await newLink.save();

    return linkId;
  } catch (error) {
    console.error("Error creating unique link ID:", error);
    throw new Error("Failed to create a unique link ID");
  }
};

export default createUniqueLinkId;
  1. 客户端组件调用方式不变,但确保Next.js版本支持Server Action(13.4+),并且在next.config.js中启用相关配置。

方案2:使用API路由(兼容所有Next.js版本)

  1. 创建app/api/create-link/route.ts服务端路由:
import { NextResponse } from "next/server";
import { v4 as uuidv4 } from "uuid";
import Link from "@/model/link";
import { connectToDB } from "@/utils/database";

export async function GET() {
  try {
    await connectToDB();
    let linkId = "";
    let isUnique = false;

    while (!isUnique) {
      linkId = uuidv4();
      const existingLink = await Link.findOne({ linkId });
      if (!existingLink) {
        isUnique = true;
      }
    }

    const newLink = new Link({ linkId });
    await newLink.save();

    return NextResponse.json({ linkId }, { status: 200 });
  } catch (error) {
    console.error("Error creating unique link ID:", error);
    return NextResponse.json(
      { error: "Failed to create a unique link ID" },
      { status: 500 }
    );
  }
}
  1. 修改客户端组件的调用逻辑:
const redirectOrSetup = async () => {
  if (profile) {
    try {
      const res = await fetch("/api/create-link");
      if (!res.ok) throw new Error("Failed to fetch link ID");
      const data = await res.json();
      router.push(`/chatroom/${data.linkId}`);
    } catch (error) {
      console.error("Failed to create chat room link", error);
    }
  }
};

额外注意事项

  • 永远不要在客户端组件中直接操作数据库或使用服务端专属库
  • 可以给useEffect的依赖数组添加profile,确保逻辑的响应性
  • 对localStorage的JSON解析结果可以增加异常捕获,避免格式错误导致的崩溃

备注:内容来源于stack exchange,提问作者Gideon Olaiya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 17:09:35