Making database queries from server components
Answered
Polar bear posted this in #help-forum
Polar bearOP
Is it allowed to make a database queries from a server components that is not a page, or not.
because I get an error when I try to do so.
the error:
because I get an error when I try to do so.
the error:
Module not found: Can't resolve 'dns'
1 | 'use strict'
2 |
> 3 | var dns = require('dns')
| ^^^^^^^^^^^^^^
4 |
5 | var defaults = require('./defaults')
6 |
https://nextjs.org/docs/messages/module-not-found
Answered by Polar bear
this maybe because I'm making the components organised in a folders, and each folder have entry
index.ts
which exports everything from the folder together, like:export * from './cards';
export * from './header';
export * from './navbar';
export * from './reusables';
export * from './theme-toggle';
export * from './filters';
export * from './tables';
export * from './forms';
export * from './featured';
export * from './footer';
16 Replies
@Polar bear Is it allowed to make a database queries from a server components that is not a page, or not.
because I get an error when I try to do so.
the error:
Module not found: Can't resolve 'dns'
1 | 'use strict'
2 |
> 3 | var dns = require('dns')
| ^^^^^^^^^^^^^^
4 |
5 | var defaults = require('./defaults')
6 |
https://nextjs.org/docs/messages/module-not-found
it is allowed.
it's likely that you are importing this component into a client component, making it a client component as well. no "use client" does not equate to the component being a server component
it's likely that you are importing this component into a client component, making it a client component as well. no "use client" does not equate to the component being a server component
Polar bearOP
the parent:
import {
BasePostCard,
Pagination,
PostCard,
SearchInput,
} from '@/components';
import { Group, SimpleGrid, Stack, Text, Title } from '@mantine/core';
import { query } from './query';
import { CharacterFilter } from '@/components/filters/character';
type Props = {
params: Promise<{ collectionId: string }>;
searchParams: Promise<{
page?: string;
surah?: string;
verse?: string;
q?: string;
}>;
};
const Collection = async ({ params, searchParams }: Props) => {
const collectionId = +(await params).collectionId;
const page = Number((await searchParams)?.page) || 1;
const surah = (await searchParams).surah ?? '';
const verse = (await searchParams).verse ?? '';
const q = (await searchParams).q ?? '';
const { collection, posts } = await query({
collectionId,
page,
surah,
verse,
q,
});
console.log('we received ', collection);
if (!posts.data.length) {
return (
<Stack>
<Title>{collection.title}</Title>
<Text>{collection.description}</Text>
<p>no posts found</p>
</Stack>
);
}
return (
<Stack>
<Title>{collection.title}</Title>
<Text>{collection.description}</Text>
<Group justify='end' align='start'>
<SearchInput />
<CharacterFilter />
{/* {resolveCollectionFilters(collection.extension)} */}
</Group>
<SimpleGrid
cols={{
base: 1,
sm: 2,
md: 3,
}}
>
{posts?.type === 'BASE' &&
posts.data.map((p) => <BasePostCard post={p} key={p.id} />)}
{posts?.type !== 'BASE' &&
posts.data.map((p) => (
<PostCard
key={p.id}
post={{
data: p,
extension: posts.type,
}}
/>
))}
</SimpleGrid>
<Pagination itemsCount={posts.count} />
</Stack>
);
};
export default Collection;
the child
import { db } from '@/db';
import { $postExtraData } from '@/db/schema';
import { eq } from 'drizzle-orm';
export const CharacterFilter = async () => {
const characters = await db
.select()
.from($postExtraData)
.where(eq($postExtraData.key, 'CHARACTER'));
console.log('where the filter is living');
return <p>hello</p>;
};
@Polar bear the child
tsx
import { db } from '@/db';
import { $postExtraData } from '@/db/schema';
import { eq } from 'drizzle-orm';
export const CharacterFilter = async () => {
const characters = await db
.select()
.from($postExtraData)
.where(eq($postExtraData.key, 'CHARACTER'));
console.log('where the filter is living');
return <p>hello</p>;
};
the code looks fine here, do you use this component in any other places? what happens if you add
import "server-only"
to the top of the component?@joulev the code looks fine here, do you use this component in any other places? what happens if you add `import "server-only"` to the top of the component?
Polar bearOP
Ahh, I was doing this:
when I commented the code, the issue solved, thank you.
import { PostExtensionEnum } from '@/db/types';
import { SurahVerseFilters } from './surah-verse';
import { CharacterFilter } from './character';
export const resolveCollectionFilters = (extension: PostExtensionEnum) => {
switch (extension) {
case 'SURAH_WITH_VERSE':
return <SurahVerseFilters />;
case 'CHARACTER':
return <CharacterFilter />;
}
};
when I commented the code, the issue solved, thank you.
but why this is making an issue?
@Polar bear Ahh, I was doing this:
tsx
import { PostExtensionEnum } from '@/db/types';
import { SurahVerseFilters } from './surah-verse';
import { CharacterFilter } from './character';
export const resolveCollectionFilters = (extension: PostExtensionEnum) => {
switch (extension) {
case 'SURAH_WITH_VERSE':
return <SurahVerseFilters />;
case 'CHARACTER':
return <CharacterFilter />;
}
};
when I commented the code, the issue solved, thank you.
hmm what if you make this
resolveCollectionFilters
a component instead?Polar bearOP
I'll try.
even this one still looks okay to me, not too sure what's wrong here. sure, a function is not the best idea here compared to a proper component but i don't see how that doesn't work either
Polar bearOP
same issue as if it is still a function.
this is not causing the problem:
import { PostExtensionEnum } from '@/db/types';
// import { SurahVerseFilters } from './surah-verse';
import { CharacterFilter } from './character';
export const ResolveCollectionFilters = ({
extension,
}: {
extension: PostExtensionEnum;
}) => {
switch (extension) {
case 'SURAH_WITH_VERSE':
return <p>hi</p>;
case 'CHARACTER':
return <p>hiii</p>;
}
};
this does cause an issue:
import { PostExtensionEnum } from '@/db/types';
// import { SurahVerseFilters } from './surah-verse';
import { CharacterFilter } from './character';
export const ResolveCollectionFilters = ({
extension,
}: {
extension: PostExtensionEnum;
}) => {
switch (extension) {
case 'SURAH_WITH_VERSE':
return <SurahVerseFilters />;
case 'CHARACTER':
return <CharacterFilter /
}
};
Polar bearOP
I think I know why this happens.
Polar bearOP
this maybe because I'm making the components organised in a folders, and each folder have entry
index.ts
which exports everything from the folder together, like:export * from './cards';
export * from './header';
export * from './navbar';
export * from './reusables';
export * from './theme-toggle';
export * from './filters';
export * from './tables';
export * from './forms';
export * from './featured';
export * from './footer';
Answer
oh yeah then that is what it is. you are still (accidentally) importing the server component into a client component despite not using the server component there
so from the import chain, it will eventually be that you are importing "dns" (from the database connection) into a client component which doesn't work