#Loading data in a .server file?

1 messages · Page 1 of 1 (latest)

inland wraith
#

Hi. I have a component that uses dexie-export-import, so I have to use the .server extension for it to work correctly. I also, need to load data from a prisma db in the same file. Is that possible?

bronze panther
#

Yep, should be totally fine.

#

Prisma is server-side only, so you can use it in a .server file no problem.

inland wraith
# bronze panther Yep, should be totally fine.

It's not working... I usually do it in a loader file:

export const loader: LoaderFunction = async ({
  request,
  params: { userName },
}) => {
  const { host } = new URL(request.url);

  const profile = await db.user.findUnique({
    where: { userName },
  });

  const userMixes = await db.mixSettings.findMany({
    where: { userId: profile?.id },
    include: { trackSettings: true },
    orderBy: {
      createdAt: "asc",
    },
  });

  const data = {
    userName,
    userMixes,
    host,
  };
  return json(data);
};
#

...but I can't use a loader file in that component.

#

Hold on. Let me try again.

bronze panther
#

Where is db coming from? Can't you just import it in your .server file?

inland wraith
#

I think the problem is that I'm using a Blob.

bronze panther
#

Ah, that would make a difference.

#

What version of Node.js?

bronze panther
#

Well there's your problem - you're importing a .server in a .client file. You can't do that.

inland wraith
bronze panther
#

In your loader file, you're using db.user etc. etc. I wondered where you were importing that from

inland wraith
#

Oh. that was just an example from anothr remix app.

bronze panther
#

Anyway, it looks like the only place you're using dexie-export-import is in this .client file.

inland wraith
#

yes

bronze panther
#

Got it.

#

Well, for starters you need to move all of your server-side code out of the .client file. It won't work in there.

#

Then you need to set up a loader in a route that performs your server-side code, and then sends it down to the client, and then have the client handle it.

#

Looks like you're generating a Blob - a binary file. You could move the code that generates that into a resource route (a route that doesn't have a default export), make sure the loader sets the appropriate content-type headers, and then use a fetch to fetch the data from that resource route in a useEffect.

inland wraith
bronze panther
#

Good luck!

inland wraith
bronze panther
#

Awesome!

inland wraith
# bronze panther Awesome!

Actually, I'm still having trouble with this. I think I need two resource routes. I got the first resource route working quickly, but I've been struggling since then to implement the second one.

The first resource route gets all the names of every entry in the db, so they can be used as values in a select input. That select input is supposed to trigger the request to the second resource route, but this time instead of getting all the values in the db, its just getting one (which is the value of event.currentTarget).

Here's a sandbox if anyone has any tips. https://stackblitz.com/edit/github-x54sew?file=app%2Fcomponents%2FMixer.tsx

inland wraith
#

how can I get this data on the server
to a component on the client?

inland wraith
# bronze panther Awesome!

Hi. Sorry, I thought I had this as soon as I got the resource route working.. Could you pleas expand on:

...then use a fetch to fetch the data from that resource route in a useEffect

Right now I have a select input that onChange triggers an importDb callback that is supposed to load a resource route and return the data from the query of the resource route.

component:

function importDb(e: React.FormEvent<HTMLSelectElement>) {
  const result = fetcher.load(`/${e.currentTarget.value}`);
  console.log("result", result); //undefined
}

resource route:

import type { LoaderFunction } from "@remix-run/node";
import { prisma } from "~/utils/db.server";

export const loader: LoaderFunction = async ({ params: { slug } }) => {
  const mixData = await prisma.mixData
    .findFirst({
      where: { name: slug },
    })
    .then((data) => JSON.stringify(data))
    .then((str) => new TextEncoder().encode(str))
    .then(
      (bytes) => new Blob([bytes], { type: "application/json;charset=utf-8" })
    );
  if (!mixData) throw new Error("Mix not found");
  const data = { mixData };
  console.log("data", data); // This logs the data I need in my component
  return new Response(mixData, {
    status: 200,
    headers: {
      "Content-Type": "application/json;charset=utf-8",
    },
  });
};
bronze panther
#

Cool. Yeah, that works.

#

Using fetch in a useEffect is just one option. Fetching from a form event is a great place to fetch too

inland wraith
#

So I just use the regular Fetch API. Not useFetcher?

bronze panther
#

Is useFetcher working for you?

#

If so, great! keep using it!

inland wraith
#

Ummm.. I'm totally confused. I'm not sure if I'm overthinking this or what? Right now, I'm not using fetch or useFetcher. I'm using fetcher.load. I think that's the problem...

bronze panther
#

Sure. It looks like you are trying to get the results directly from fetcher.load. That's not how it works. fetcher.load will fetch the data, but then make it available on fetcher.data. So you can't just console.log it from your importDb function.

Besides, you aren't even awaiting it at this point.

#

Don't overthink it. Maybe just try fetch

inland wraith
#

I was awating but I removed it becuse VSCode said it had no effect.

bronze panther
#

Yeah, because fetcher.load doesn't return results. It loads the results into fetcher.data.

inland wraith
#

oh