reactjs mongoose__WEBPACK_IMPORTED_MONOSE_.不是函数

twh00eeo  于 11个月前  发布在  React
关注(0)|答案(2)|浏览(88)

当我在一个Next.JS项目(托管在Heroku上)工作时,我有以下问题。
这是主文件的内容(对于我的问题)DB_ChanList.tsx:

'use client';

import Link from 'next/link';
import channelsPool from "@/lib/channels";
import React from 'react';
import {useState,useEffect} from 'react';

export default function DB_ChanList() {
  const [listDisplay,setListDisplay] = useState(true);
  const theChannels = channelsPool()

  const swapDisplay = (e: React.MouseEvent<HTMLButtonElement>) => {
    e.preventDefault()
    setListDisplay(!listDisplay)
  } /* End of swapDisplay */

  return <div>
        {listDisplay &&
      Object.values(theChannels).map(item => (
                <div key={item as string}>
          <button onClick={(e)=>swapDisplay(e)} value={item}>
            <b>{item}</b>
          </button>
                </div>
            ))
        }
        {!listDisplay &&
      <div>THE:unitID::</div>
        }
    </div>
} /* End of DB_ChanList */

字符串
这是文件通道的内容.tsx:

import mongoose, {Schema,Model,models} from "mongoose"
import connectMDB from "./mongoDB"

export default async function channelsPool() {
    const speakSchema = new Schema({
        channelID: {
            type: String,
            required: true
        },
        voiceRecordID: {
            type: String,
            required: true
        },
        timeStamp: {
            type: Number,
            required: true
        }
    })

    interface SpeakDoc extends Document {
        channelID: string
        voiceRecordID: string
        timeStamp: number
    }

    interface SpeakModel extends Model<SpeakDoc> {}

    const theModel = (models && models.Voice) ? (models.Voice as SpeakModel) :
                                            mongoose.model<SpeakDoc, SpeakModel>
                                                    ('Voice',speakSchema,'vxads')

    await connectMDB()

    try {
        console.log('MDB_URI_AUDIO(T)=',process.env.MDB_URI_AUDIO)
        const theResult = await theModel
        .find({},'channelID').distinct('channelID')
  
        return theResult
    } catch (error) {
        console.log('MDB_URI_AUDIO(E)=',process.env.MDB_URI_AUDIO)
        console.error("Error in channelsPool:", error);
        throw error; // Rethrow the error to propagate it.
    }
} /* End of channelsPool */


最后,这是mongoDB.tsx文件的内容:

import mongoose from "mongoose"

const uri = process.env.MDB_URI_AUDIO!,
            connectMDB = async () => mongoose.connect(uri)

export default connectMDB


使用上面的所有源,我得到这个错误消息,与最后一个文件有关:

TypeError: mongoose__WEBPACK_IMPORTED_MODULE_0___default().connect is not a function


在网上搜索了一些调查之后,它看起来像是mongoDB.tsx中的代码,尽管在服务器组件中使用时工作正常,但不适合在客户端组件中使用。我如何解决这种情况并在这里访问我的数据库?

ffscu2ro

ffscu2ro1#

您正在尝试连接到客户端组件中的mongoose。
我能想到两种方法来解决这个问题。

方法一

您可以将使用channelPools的客户端组件 Package 在服务器组件中。
新组件<DB_ChanList_SC />

// DB_ChanList_SC.tsx
import React from "react";

import channelsPool from "@/lib/channels";
import DB_ChanList from "./DB_ChanList";

const DB_ChanList_SC = async () => {
  const theChannels = await channelsPool();
  return <DB_ChanList theChannels={theChannels} />;
};

export default DB_ChanList_SC;

字符串
编辑<DB_ChanList />theChannels为 prop

// DB_ChanList.tsx
"use client";

import Link from "next/link";
import React from "react";
import { useState, useEffect } from "react";

export default function DB_ChanList({
  theChannels,
}: {
  theChannels: string[];
}) {
  const [listDisplay, setListDisplay] = useState(true);

  const swapDisplay = (e: React.MouseEvent<HTMLButtonElement>) => {
    e.preventDefault();
    setListDisplay(!listDisplay);
  }; /* End of swapDisplay */

  return (
    <div>
      {listDisplay &&
        Object.values(theChannels).map((item) => (
          <div key={item as string}>
            <button onClick={(e) => swapDisplay(e)} value={item}>
              <b>{item}</b>
            </button>
          </div>
        ))}
      {!listDisplay && <div>THE:unitID::</div>}
    </div>
  );
}  /* End of DB_ChanList */


在使用<DB_ChanList />的地方,可以将其替换为服务器组件

<>
      {/* <DB_ChanList /> */}
      <DB_ChanList_SC />
    </>


请注意,此方法仅适用于在其他服务器组件中使用<DB_ChanList_SC />的情况,如果在客户端组件中使用,则不起作用。

方法二

创建一个API路由,以channelPool的结果进行响应
/api/channels-pool上创建一个新的API端点,此端点将运行函数并返回结果

// src/app/api/channels-pool/route.ts

import channelsPool from "@/lib/channels";
import { NextResponse } from "next/server";

export type ChannelsPoolResponseType = Awaited<ReturnType<typeof channelsPool>>;

export const GET = async (req: Request) => {
  const theChannels = await channelsPool();
  return NextResponse.json(theChannels);
};


修改<DB_ChanList />以使用fetch获取数据

"use client";

import type { ChannelsPoolResponseType } from "@/app/api/channels-pool/route";
import Link from "next/link";
import React from "react";
import { useState, useEffect } from "react";

export default function DB_ChanList() {
  const [theChannels, setTheChannels] = useState<ChannelsPoolResponseType>([]);
  const [listDisplay, setListDisplay] = useState(true);

  const swapDisplay = (e: React.MouseEvent<HTMLButtonElement>) => {
    e.preventDefault();
    setListDisplay(!listDisplay);
  }; /* End of swapDisplay */

  const fetchChannels = async () => {
    const res = await fetch("/api/channels-pool");
    const json = await res.json();
    setTheChannels(json);
  };

  useEffect(() => {
    fetchChannels();
  }, []);

  return (
    <div>
      {listDisplay &&
        Object.values(theChannels).map((item) => (
          <div key={item as string}>
            <button onClick={(e) => swapDisplay(e)} value={item}>
              <b>{item}</b>
            </button>
          </div>
        ))}
      {!listDisplay && <div>THE:unitID::</div>}
    </div>
  );
} /* End of DB_ChanList */

hgtggwj0

hgtggwj02#

为什么要在服务器组件之外使用它?Webpack似乎很难正确捆绑它,因为客户端代码是捆绑的。Mongoose使用本机nodejs模块,这些模块不能被webpack打包用于客户端服务。
编辑:永远记住,nodejs的本地模块不能被webpack打包用于客户端服务。有一些变通方法,但不值得相信我....除非你想要100+ MB的捆绑包

相关问题