When working on a Next.JS project (hosted on Heroku) I have the following isssue.
This is the content of the main file (for my problem) 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 */
This is the content of the file channels.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 */
And finally this is the content of the file mongoDB.tsx:
import mongoose from "mongoose"
const uri = process.env.MDB_URI_AUDIO!,
connectMDB = async () => mongoose.connect(uri)
export default connectMDB
With all the sources above I get this error message, relating to the last file :
TypeError: mongoose__WEBPACK_IMPORTED_MODULE_0___default().connect is not a function
After some investigations searching the net, it seems like the code in mongoDB.tsx, though working fine when used in a server component is not appropriate for use in a client component. What is the way for me to solve this situation and access my database here ?
2
Answers
Why using it outside server component??? Webpack seems to find it hard to bundle it correctly because client side code is bundled. Mongoose uses native nodejs modules and these modules can not be packed by webpack for client side serving.
Edit:
Always remember that nodejs native modules can not be packed by webpack for client side serving. There are workarounds but it doesnt worth it trust me…. Unless u want 100+ MB bundles
You are attempting to connect to mongoose in a client component.
There are two methods I could think of to solve this.
Method 1
You may wrap the wrap the client components that consumes
channelPools
with a server component. In effect running the function on a server component before passing it down to a client component as propsNew component
<DB_ChanList_SC />
Editied
<DB_ChanList />
takestheChannels
as propsAnd where you used
<DB_ChanList />
, you would replace it with the server componentNote that this method only works if
<DB_ChanList_SC />
is used inside other server components and will not work if used inside a client component.Method 2
Make an API route that responds with the results of
channelPool
Create a new API endpoint at
/api/channels-pool
, this endpoint will run the function and return the resultsModify
<DB_ChanList />
to usefetch
to get data