DT
Drizzle Team•12mo ago
Rorsch

net::ERR_NAME_NOT_RESOLVED showing multiple times on the console

Hello, I'm trying to do simple database access using drizzle orm. The data got fetched, but my console has been showing a lot of the error index.js: POST https://undefined/psdb.v1alpha1.Database/Execute net::ERR_NAME_NOT_RESOLVED This is the code that I use to fetch my data.
export default async function getCustomers() {
try {
const data = await db.select().from(customers);
return data;
} catch (error) {
console.error("Database Error:", error);
throw new Error("Failed to get customers data.");
}
}
export default async function getCustomers() {
try {
const data = await db.select().from(customers);
return data;
} catch (error) {
console.error("Database Error:", error);
throw new Error("Failed to get customers data.");
}
}
this is the db setup
import * as schema from "@/app/db/schema";
import { drizzle } from "drizzle-orm/planetscale-serverless";
import { connect } from "@planetscale/database";

const connection = connect({
url: process.env["DATABASE_URL"],
});

export const db = drizzle(connection, { schema });
import * as schema from "@/app/db/schema";
import { drizzle } from "drizzle-orm/planetscale-serverless";
import { connect } from "@planetscale/database";

const connection = connect({
url: process.env["DATABASE_URL"],
});

export const db = drizzle(connection, { schema });
and this is the drizzle.config.ts
import { defineConfig } from "drizzle-kit";
export default defineConfig({
schema: "./app/db/schema.ts",
driver: "mysql2",
out: "./app/drizzle/",
dbCredentials: {
uri: process.env["DATABASE_URL"] || "",
},
verbose: true,
strict: true,
});
import { defineConfig } from "drizzle-kit";
export default defineConfig({
schema: "./app/db/schema.ts",
driver: "mysql2",
out: "./app/drizzle/",
dbCredentials: {
uri: process.env["DATABASE_URL"] || "",
},
verbose: true,
strict: true,
});
Solution:
1. Keep page as server component. fetch the data on this page. 2. make the modal accept the data as a prop from the page. this will come in when the promise resolves. 3. when the user opens the modal which is actually a client component, the data will be in there. IF you need the data to be populated based on actions from within the modal, you can do so via server actions. if you only need the data populated via initial page load, then the above is no problems....
Jump to solution
18 Replies
Angelelz
Angelelz•12mo ago
Can you verify that your application have acces to those environment variables?
Rorsch
RorschOP•12mo ago
i am currently the app locally, and i can confirm that the host, username, and password is not empty. My data did get fetched from planestscale. this is what Connection looks like (sensitive data are removed)
Connection {
session: null,
config: {
url: 'mysql://removed:[email protected]/removed?ssl={"rejectUnauthorized":true}',
fetch: [AsyncFunction (anonymous)] {
__nextGetStaticStore: [Function (anonymous)],
__nextPatched: true
},
username: 'removed',
password: 'pscale_pw_REMOVED',
host: 'aws.connect.psdb.cloud'
},
url: 'https://aws.connect.psdb.cloud/removed'
}
Connection {
session: null,
config: {
url: 'mysql://removed:[email protected]/removed?ssl={"rejectUnauthorized":true}',
fetch: [AsyncFunction (anonymous)] {
__nextGetStaticStore: [Function (anonymous)],
__nextPatched: true
},
username: 'removed',
password: 'pscale_pw_REMOVED',
host: 'aws.connect.psdb.cloud'
},
url: 'https://aws.connect.psdb.cloud/removed'
}
and this is what the db from drizzle
MySqlDatabase {
dialect: MySqlDialect {},
session: PlanetscaleSession {
dialect: MySqlDialect {},
baseClient: Connection {
session: null,
config: [Object],
url: 'https://aws.connect.psdb.cloud/removed'
},
schema: {
fullSchema: [Object [Module]],
schema: [Object],
tableNamesMap: [Object]
},
options: { logger: undefined },
client: Connection {
session: null,
config: [Object],
url: 'https://aws.connect.psdb.cloud/removed'
},
logger: NoopLogger {}
},
mode: 'planetscale',
_: {
schema: { customers: [Object], orders: [Object] },
tableNamesMap: { customer: 'customers', order: 'orders' }
},
query: {
customers: RelationalQueryBuilder {
fullSchema: [Object [Module]],
schema: [Object],
tableNamesMap: [Object],
table: [MySqlTable],
tableConfig: [Object],
dialect: MySqlDialect {},
session: [PlanetscaleSession],
mode: 'planetscale'
},
orders: RelationalQueryBuilder {
fullSchema: [Object [Module]],
schema: [Object],
tableNamesMap: [Object],
table: [MySqlTable],
tableConfig: [Object],
dialect: MySqlDialect {},
session: [PlanetscaleSession],
mode: 'planetscale'
}
}
}
MySqlDatabase {
dialect: MySqlDialect {},
session: PlanetscaleSession {
dialect: MySqlDialect {},
baseClient: Connection {
session: null,
config: [Object],
url: 'https://aws.connect.psdb.cloud/removed'
},
schema: {
fullSchema: [Object [Module]],
schema: [Object],
tableNamesMap: [Object]
},
options: { logger: undefined },
client: Connection {
session: null,
config: [Object],
url: 'https://aws.connect.psdb.cloud/removed'
},
logger: NoopLogger {}
},
mode: 'planetscale',
_: {
schema: { customers: [Object], orders: [Object] },
tableNamesMap: { customer: 'customers', order: 'orders' }
},
query: {
customers: RelationalQueryBuilder {
fullSchema: [Object [Module]],
schema: [Object],
tableNamesMap: [Object],
table: [MySqlTable],
tableConfig: [Object],
dialect: MySqlDialect {},
session: [PlanetscaleSession],
mode: 'planetscale'
},
orders: RelationalQueryBuilder {
fullSchema: [Object [Module]],
schema: [Object],
tableNamesMap: [Object],
table: [MySqlTable],
tableConfig: [Object],
dialect: MySqlDialect {},
session: [PlanetscaleSession],
mode: 'planetscale'
}
}
}
when i try to execute using planetscale's execute like below, it did hit my planetscale's database:
const results = await conn.execute('select 1 from dual where 1=?', [1])
console.log(results)
const results = await conn.execute('select 1 from dual where 1=?', [1])
console.log(results)
is it because drizzle(connection)'s session is null? i somewhat found the problem, it is because the page that is used for containing the Customers Table is using "use client". by removing the "use client", the database is being fetched fine. but now i am stuck since i need to have the "use client" to use NextJS's useState to control modal's open/close from another button component. but i think the problem is no longer in drizzle's scope. I will have to think of another way to not include useState in the page, so that i won't need to use "use client"
Angelelz
Angelelz•12mo ago
You have to create a client component and pass it the data from a server component. That's the new model
Rorsch
RorschOP•12mo ago
can you give me an example for my case? i have the page like below,
"use client"
page.tsx

export default function Page() {

const [open, setOpen] = useState(false);
return (
<div>
<button
type="button"
onClick={() => {
setOpen(true);
}}
>
Add New Customer
</button>
<CustomersTable />
<AddCustomerModal open={open} setOpen={setOpen} />
</div>
);
}
"use client"
page.tsx

export default function Page() {

const [open, setOpen] = useState(false);
return (
<div>
<button
type="button"
onClick={() => {
setOpen(true);
}}
>
Add New Customer
</button>
<CustomersTable />
<AddCustomerModal open={open} setOpen={setOpen} />
</div>
);
}
and the table like below
customers-table.tsx

export default async function CustomersTable() {
const customers: Customer[] = await getCustomers();

return (
<div>
...
<tbody>
{customers.map((customer) => (
<tr key={customer.email}>
<td>
{customer.fullName}
</td>
....
</tr>
))}
...
</div>
);
}
customers-table.tsx

export default async function CustomersTable() {
const customers: Customer[] = await getCustomers();

return (
<div>
...
<tbody>
{customers.map((customer) => (
<tr key={customer.email}>
<td>
{customer.fullName}
</td>
....
</tr>
))}
...
</div>
);
}
I'm watching several videos right now, and one of them mentioned that the server component needs to be wrapped inside a client component? From what I understand, the CustomersTable is a server component, so I need to create a client component, to pass the data? how can I achieve it? does that mean i should use next js' routes to fetch the data through the API? and pass the customers table as a client component?
MR BIG
MR BIG•12mo ago
@Rorsch on your page which is a server component by default, fetch the data either on it or via a server action, then pass that data through to your table (being the client component) as a prop.
MR BIG
MR BIG•12mo ago
with this code example it shows that they are using fetch (disregard the parallel reference). replace that fetch call with a call to your database via drizzle instead. this is occuring on the page which runs in the server by default. https://nextjs.org/docs/app/building-your-application/data-fetching/patterns#parallel-data-fetching
Data Fetching: Data Fetching Patterns and Best Practices | Next.js
Learn about common data fetching patterns in React and Next.js.
Rorsch
RorschOP•12mo ago
@MR BIG okay, I just realized that the problem i'm having right now is not about fetching the data, but how to keep the page as a server component, but i can still control the modal view's state using a button. the page looks something like this
No description
Rorsch
RorschOP•12mo ago
because if i force the whole page to be a client component, the table won't work, as it is a server component
MR BIG
MR BIG•12mo ago
so it can get very confusing with the new paradigm. - if your component uses any sort of react hook such as state, effect or context, it needs to be in a client component - if your component uses any interactables such as onClick, it needs to be in a client component.
- if you want to load the data from the server on initial you have two options. 1. pass the data as a prop to the client component 2. have the client component expose children as say, a react node then populate the data accordingly. note: to make this even more confusing for you, if you expose children as a prop and go that route, the data that you "stuff" into children will remain in the server context. This is how wrapping certain components as client components such as providers seem to work fine in a similar context despite it looking like a server component.
MR BIG
MR BIG•12mo ago
it can be a bit like that, some of it can kinda tunnel idk how best to describe it hahah\
Rorsch
RorschOP•12mo ago
so, since i need to have a usestate on the page to handle the modal, probably the approach that i can do is: - make the whole page as a client component - make the table a client component - create function to fetch the data from drizzle db, set this as a server function - pass the customers data to table as a prop did i get it right? unless there is a way to control modal view without using useState and onClick, like using query string, there's no other way to handle this problem like /dashboard/customers?open-modal=true
Solution
MR BIG
MR BIG•12mo ago
1. Keep page as server component. fetch the data on this page. 2. make the modal accept the data as a prop from the page. this will come in when the promise resolves. 3. when the user opens the modal which is actually a client component, the data will be in there. IF you need the data to be populated based on actions from within the modal, you can do so via server actions. if you only need the data populated via initial page load, then the above is no problems.
MR BIG
MR BIG•12mo ago
modal is client component** this is what im working on right now actually so the client component looks along the lines of this
"use client"
xxxxx

export const AddToInvoiceDialog = async ({
clients,
}: {
clients: {
id: number | null;
name: string | null;
entries: number;
}[];
}) => {
const [open, setOpen] = useState(false);

return (
<div>
<Dialog
open={open}
onOpenChange={(val) => {
setOpen(val);
}}
>
<DialogTrigger asChild>
<Button variant="primary" icon={faPlus} iconPosition="left">
New Invoice
</Button>
</DialogTrigger>
<DialogContent className="md:max-w-5xl">
<DialogHeader>
<DialogTitle>Add To Invoice</DialogTitle>
<DialogDescription>
Add approved time entries to an invoice.
</DialogDescription>
</DialogHeader>
{JSON.stringify(clients)}
</DialogContent>
</Dialog>
</div>
);
};
"use client"
xxxxx

export const AddToInvoiceDialog = async ({
clients,
}: {
clients: {
id: number | null;
name: string | null;
entries: number;
}[];
}) => {
const [open, setOpen] = useState(false);

return (
<div>
<Dialog
open={open}
onOpenChange={(val) => {
setOpen(val);
}}
>
<DialogTrigger asChild>
<Button variant="primary" icon={faPlus} iconPosition="left">
New Invoice
</Button>
</DialogTrigger>
<DialogContent className="md:max-w-5xl">
<DialogHeader>
<DialogTitle>Add To Invoice</DialogTitle>
<DialogDescription>
Add approved time entries to an invoice.
</DialogDescription>
</DialogHeader>
{JSON.stringify(clients)}
</DialogContent>
</Dialog>
</div>
);
};
const Page = async () => {
const clients = await getApprovedClientList();
return (
<div className="flex flex-1 flex-col gap-4 p-4 md:gap-8 md:p-10">
<div className="flex justify-between">
<div>
<h1 className="text-2xl font-bold">Invoices</h1>
<h5></h5>
</div>
<div>
<AddToInvoiceDialog clients={clients} />
</div>
</div>
<div>
xxxx
const Page = async () => {
const clients = await getApprovedClientList();
return (
<div className="flex flex-1 flex-col gap-4 p-4 md:gap-8 md:p-10">
<div className="flex justify-between">
<div>
<h1 className="text-2xl font-bold">Invoices</h1>
<h5></h5>
</div>
<div>
<AddToInvoiceDialog clients={clients} />
</div>
</div>
<div>
xxxx
there i call a server action getApprovedClientList however just using a normal drizzle query is perfectly fine
Rorsch
RorschOP•12mo ago
1 question, in my case, the dialog won't be opened until the Add New Customer button is clicked. In your case, Button to show the Dialog is inside the Dialog component itself. Ah, then I probably will just move the Button inside the Modal component, instead of having it as 2 separate components that way, the Modal and Button can be a client component, and the page still can be a server component
MR BIG
MR BIG•12mo ago
yep so the button is inside the dialog so the component has access to change the open state
Rorsch
RorschOP•12mo ago
right right, thanks a lot! I'm new to next js and these kind of stuffs, and I've been stuck for 2 days hahaha
MR BIG
MR BIG•12mo ago
its not easy. the whole app router rollout has been tricky at best due to not very clear communication so it takes a lot of random reading and videos to get the hang of. thats what i did anyway 🙂
Want results from more Discord servers?
Add your server