Mordi
Mordi
TTCTheo's Typesafe Cult
Created by Mordi on 1/12/2024 in #questions
server side auth & react query
I am migration a old project that used t3 & nextjs 12. I have removed the old t3-stuff, such as sessionProvider, and am trying to just use getServerAuthSession instead of useSession as it seems to be the preferred way to auth. But How do I deal with components that used auth and fetched data. I want to use getServerAuthSession, meaning the component has to be a server component. But I also need to fetch some data, via react-query, so the component has to be a client component. Reading through the docs of react-query, they use HydrationBoundary to prefetch on the server then they dehydrate and pass it as props a client component. But this gives me an error on the import of HydrationBoundary: "Module '"@tanstack/react-query"' has no exported member 'HydrationBoundary'." TLDR: I don't know what steps to take to migrate a pages (client) component like this: https://github.com/Mordi490/lineup-larry/blob/main/src/pages/lineup/%5Bid%5D.tsx to app router. Check out the "chore/nextjs_13_migration"-branch if you want to see the latest progress on the app router migration. - has auth & uses auth to render the page differently, but I want to use getServerAuthSession since that seems to be the recommendation ==> server side comp - uses react-query to fetch data ==> client component
4 replies
TTCTheo's Typesafe Cult
Created by Mordi on 4/5/2023 in #questions
typedefs for useState across components with object arrays
We have a Parent and a Child component. inside of parent we init the following state:
const [objects, setObjects] = useState<
{ url: string; partNumber: number }[]>([]);
const [objects, setObjects] = useState<
{ url: string; partNumber: number }[]>([]);
we want this state to be shared between our two components inside of Parent we render a Child passing the state as props
<Child objects={objects} setObjects={(e) => setStateHelper(e)} />
<Child objects={objects} setObjects={(e) => setStateHelper(e)} />
inside of our Child component we define our props and eventually we may want to update the state.
const Child = ({objects, setObjects}: {objects: {url: string, partNumber: number }[]; setObjects: (e: { url: string, partNumber: number}[]) => void; }) => {
... component does stuff, eventually we want to update the state
setObjects(newObject)
}
const Child = ({objects, setObjects}: {objects: {url: string, partNumber: number }[]; setObjects: (e: { url: string, partNumber: number}[]) => void; }) => {
... component does stuff, eventually we want to update the state
setObjects(newObject)
}
Right now I am getting an trying to create a helper function in the parent component so I don't have do deal with the setState types, eg.
Dispatch<SetStateAction<{
url: string;
partNumber: number;
}[]>>
Dispatch<SetStateAction<{
url: string;
partNumber: number;
}[]>>
in the child component The current one I have looks like the following:
const setStateHelper = (urls: { url: string; partNumber: number; }[]) => {
setObjects((prevState) => [...prevState, urls]);
}
const setStateHelper = (urls: { url: string; partNumber: number; }[]) => {
setObjects((prevState) => [...prevState, urls]);
}
The problem is that I am getting a ts(2345) error, a type mismatch. Argument of type '(prevState: { url: string; partNumber: number; }[]) => ({ url: string; partNumber: number; } | { url: string; partNumber: number; }[])[]' is not assignable to parameter of type 'SetStateAction<{ url: string; partNumber: number; }[]>'.
2 replies
TTCTheo's Typesafe Cult
Created by Mordi on 3/29/2023 in #questions
how come this returns undefined
55 replies
TTCTheo's Typesafe Cult
Created by Mordi on 3/24/2023 in #questions
Am I using useState incorrectly here?
For context I am attempting to to set up multipart uploads to S3, and yes I did see https://github.com/nramkissoon/t3-s3 and my code is based on that. I have these two useState:
const [uploadId, setUploadId] = useState<string[]>([]);
const [partPresignedUrls, setPartPresignedUrls] = useState<{ [partNumber: number]: File }[]>(
[]
);
const [uploadId, setUploadId] = useState<string[]>([]);
const [partPresignedUrls, setPartPresignedUrls] = useState<{ [partNumber: number]: File }[]>(
[]
);
These states get updated based on a trpc call:
fetchPresignedUrls({ fileName: file.name, filePartTotal: Object.keys(parts).length })
.then((res) => {
const urls = res.urls.map((data) => ({
url: data.url,
partNumber: data.partNumber,
}));
console.log("FE has now received the following urls: ", urls)
console.log("FE has now received the following uploadId: ", res.uploadId)
setPresignedUrl([...presignedUrl, urls]);
setUploadId([...uploadId, res.uploadId]);
})
.catch((err) => console.log(err));
}
fetchPresignedUrls({ fileName: file.name, filePartTotal: Object.keys(parts).length })
.then((res) => {
const urls = res.urls.map((data) => ({
url: data.url,
partNumber: data.partNumber,
}));
console.log("FE has now received the following urls: ", urls)
console.log("FE has now received the following uploadId: ", res.uploadId)
setPresignedUrl([...presignedUrl, urls]);
setUploadId([...uploadId, res.uploadId]);
})
.catch((err) => console.log(err));
}
But the useState only saves the data for the last file. From the console.log I know that I do receive the urls and the uploadId, for both the client and server.
8 replies
TTCTheo's Typesafe Cult
Created by Mordi on 3/1/2023 in #questions
Updating profile pictures from next-auth providers
3 replies
TTCTheo's Typesafe Cult
Created by Mordi on 2/19/2023 in #questions
React-Dropzone, useState & dnd-kit struggles
What I want to achieve is the ability to drag image previews to change the order of the images, ie. something like this: https://codesandbox.io/s/dndkit-sortable-image-grid-py6ve?file=/src/App.jsx The images & their preview come from a react-dropzone component. There is a solid chance this is irrelevant to my issue but mentioning it to be sure. My initial plan was to have a state in the react-dropzone component inside of the onDrop: that will populate the useState into the following shape: { id: number, src: File }. This approach is similar to the example in the first codesandbox. but I don't see how I can do this without a useEffect, which feels overkill since this is really close to what I want to achieve: https://github.dev/HamedBahram/dropzone here is a sandbox to better illustrate the situation: https://codesandbox.io/s/mystifying-germain-cs1hsl?file=/src/App.tsx Look at the block comment inside onDrop:
1 replies
TTCTheo's Typesafe Cult
Created by Mordi on 2/9/2023 in #questions
RHF & react-dropzone integration
8 replies
TTCTheo's Typesafe Cult
Created by Mordi on 1/30/2023 in #questions
Ternary statements with possible null/undefined
I am working with an object with the following shape:
{ image: string, previewImg: number }
{ image: string, previewImg: number }
images is just a string with UUIDs separated by commas. If the UUID is for a video they are prefixed with "video-". Example: "abc,xyz,video-abc" I am mapping over a collection of the given shape and previewing a single image for each object, and as you've prob guessed the previewImg decides which image to preview. ex:
shapeCollection.map((shape) => (
<Image
src={`<my-s3-bucket>/${shape.image.split(",")[shape.previewImg]}`}
/>
))
shapeCollection.map((shape) => (
<Image
src={`<my-s3-bucket>/${shape.image.split(",")[shape.previewImg]}`}
/>
))
So the issue arises when the previewImg selects a video. I need a placeholder image. To solve this I thought a simple Ternary would be sufficient, ie:
{shape.image.split(",")[shape.previewImg]?.includes("video") ? (
// it's a video, use placeholder img
<Image src={placeholder} />
) : (
// not a video
<Image
src={`<my-s3-bucket>/${shape.image.split(",")[shape.previewImg]}`}
/>
)}
{shape.image.split(",")[shape.previewImg]?.includes("video") ? (
// it's a video, use placeholder img
<Image src={placeholder} />
) : (
// not a video
<Image
src={`<my-s3-bucket>/${shape.image.split(",")[shape.previewImg]}`}
/>
)}
This ends up always showing the false result of the ternary. the funny thing is that if I use
shape.image.split(",").includes("video")
shape.image.split(",").includes("video")
it will show the placeholder image, but then it shows it also shows the placeholder img when the previewImg was intended. I suspect that the ?. is doing something but I have no idea how or why
2 replies
TTCTheo's Typesafe Cult
Created by Mordi on 1/6/2023 in #questions
odd runtime error but just for mobile
1 replies
TTCTheo's Typesafe Cult
Created by Mordi on 11/2/2022 in #questions
Best way to validate multiple files via Zod & RHF
So I am adding validation to a form and I want to validate as much as possible on the frontend. Now I do believe some validation needs to be done by the backend, but I'll handle that after I've figured out what already has been validated by the frontend. The things I want to validate are the following: - The user has selected/uploaded at least 3 files for the form - The files are of a accepted file type - The combined size of all files does not exceed a certain threshold My initial thought was to just add the following to the form schema:
image: z.any().array().min(3, { message: "At least 3 files are required" }),
image: z.any().array().min(3, { message: "At least 3 files are required" }),
But the files are not in an array, they are instead bundled in an object like so:
"image": {
"0": {},
"1": {},
"2": {}
}
"image": {
"0": {},
"1": {},
"2": {}
}
So the first hurdle becomes how do I translate this into a Zod shape? This doesn't work
image: z.object({string: z.string(), fileBlob: z.any()})
image: z.object({string: z.string(), fileBlob: z.any()})
And is there a better way to select a specific file and perform operations, eg: formInput.image?.[1].type The data comes from a simple input
<input
type="file"
multiple
{...register("image")}
disabled={isSubmitting}
accept=".jpg, .jpeg, .png, .webp, .mp4"
/>
<input
type="file"
multiple
{...register("image")}
disabled={isSubmitting}
accept=".jpg, .jpeg, .png, .webp, .mp4"
/>
Most of the examples I've seen online are mainly focused around single files and make the assumption that formInput.image?.[0] exists.
12 replies
TTCTheo's Typesafe Cult
Created by Mordi on 10/18/2022 in #questions
T3 & Plausible proxy setup
I am having a some issues configuring plausible as a proxy on my t3-project running on Vercel. Since I am using NextJS & Vercel I want to use next-plausible and I am following the example on their gh-page. https://github.com/4lejandrito/next-plausible#proxy-the-analytics-script My next.config.mjs looks like this
import { withPlausibleProxy } from "next-plausible";

function defineNextConfig(config) {
return withPlausibleProxy()({ config });
}

export default defineNextConfig({
// your custom config....
})
import { withPlausibleProxy } from "next-plausible";

function defineNextConfig(config) {
return withPlausibleProxy()({ config });
}

export default defineNextConfig({
// your custom config....
})
when running the app I get warnings saying that warn - Invalid next.config.js options detected: ... which is true since config properties like whitelisted pages to receive images from are not being read. I am almost 100% sure I am doing something wrong with this step from the docs:
const { withPlausibleProxy } = require('next-plausible')

module.exports = withPlausibleProxy()({
// ...your next js config, if any
})
const { withPlausibleProxy } = require('next-plausible')

module.exports = withPlausibleProxy()({
// ...your next js config, if any
})
also does anyone know how well plausible proxied deals with Brave & ublock origin?
5 replies
TTCTheo's Typesafe Cult
Created by Mordi on 10/13/2022 in #questions
filter approaches on endpoints
Is there a preferred approach when it comes to adding filters to endpoints. There are two approaches I can think of. 1: Create a endpoint for each filter option, eg. "get-most-viewed", "get-most-recent", "get-highest-rated". 2: Have a singular endpoint that takes in an optional input and based on the value on the input queries for the data we want. Is one approach preferred over the other , if so why?
3 replies
TTCTheo's Typesafe Cult
Created by Mordi on 10/12/2022 in #questions
Unable to apply certain CSS-attributes to Radix components
I am working on a dropdown menu and text-based properties like text-xl, font-medium were applied, but not bg-lime-400 Looking at the DOM I can see that bg-lime-400 is in the classname, but looking at the styles tab in dev tools I see no mention of background-color being applied or overridden. Here is the code snippet in case it proves useful:
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<Image
src={session.user.image}
width={64}
height={64}
className="rounded-full"
alt="Discord profile picture"
/>
</DropdownMenu.Trigger>
<DropdownMenu.Portal className="bg-lime-400">
<DropdownMenu.Content className="bg-lime-400 text-xl">
<DropdownMenu.Item className="bg-lime-400">
<Link href={`/${session.user.id}/lineups`}>
<a>Your Lineups</a>
</Link>
</DropdownMenu.Item>
<DropdownMenu.Item>
<Link href={`/create`}>
<a>Submit Lineup</a>
</Link>
</DropdownMenu.Item>
<DropdownMenu.Item>
<Link href={`/user/${session.user.id}`}>
<a>View Profile</a>
</Link>
</DropdownMenu.Item>
<DropdownMenu.Separator className="my-1 h-px bg-gray-700" />
<DropdownMenu.Item>
<Link href={`/api/auth/signout`}>
<a>Logout</a>
</Link>
</DropdownMenu.Item>
<DropdownMenu.Arrow />
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu.Root>
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<Image
src={session.user.image}
width={64}
height={64}
className="rounded-full"
alt="Discord profile picture"
/>
</DropdownMenu.Trigger>
<DropdownMenu.Portal className="bg-lime-400">
<DropdownMenu.Content className="bg-lime-400 text-xl">
<DropdownMenu.Item className="bg-lime-400">
<Link href={`/${session.user.id}/lineups`}>
<a>Your Lineups</a>
</Link>
</DropdownMenu.Item>
<DropdownMenu.Item>
<Link href={`/create`}>
<a>Submit Lineup</a>
</Link>
</DropdownMenu.Item>
<DropdownMenu.Item>
<Link href={`/user/${session.user.id}`}>
<a>View Profile</a>
</Link>
</DropdownMenu.Item>
<DropdownMenu.Separator className="my-1 h-px bg-gray-700" />
<DropdownMenu.Item>
<Link href={`/api/auth/signout`}>
<a>Logout</a>
</Link>
</DropdownMenu.Item>
<DropdownMenu.Arrow />
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu.Root>
1 replies
TTCTheo's Typesafe Cult
Created by Mordi on 9/29/2022 in #questions
Odd Tailwind behaviour, unable to apply certain rules
I am doing ordinary flexbox stuff using tailwind. I wanted to apply justify-around to a div, but it doesn't apply. I open devtools, see that the classname is correct. I check the styles tab in the devtools, the property has not been applied, eg. no mention of justify-content: space-around I try to apply a different property this time as a sanity check, this time it's justify-center. It works, I use the devtools to manually change the value from center to space-around. It works as expected. I switch back the justify-around classname, the justify-content: <your_value> property disappears from the styles tab. I tried other classnames (justify-<evenly | start | end | between) some work, others don't and I have no idea why. If I manually change them in the devtools all of them work.
9 replies
TTCTheo's Typesafe Cult
Created by Mordi on 9/22/2022 in #questions
TS-newbie struggles with TS via NextJS Layout
I am creating a simple layout file that looks like this:
type Props = {
children: ReactNode;
title?: string;
};

const Layout = ({ children, title }: Props) => {
return (
<div>
<Nav title={title}/>
<main>{children}</main>
<Footer />
</div>
);
};
type Props = {
children: ReactNode;
title?: string;
};

const Layout = ({ children, title }: Props) => {
return (
<div>
<Nav title={title}/>
<main>{children}</main>
<Footer />
</div>
);
};
The Nav is structured to optionally taking a string prop to set as a title for for Head:
const Nav = (title?: string) => {
<Head>
{title?.length ? <title>{title}</title> : <title>Lineup Larry</title>}
</Head>
const Nav = (title?: string) => {
<Head>
{title?.length ? <title>{title}</title> : <title>Lineup Larry</title>}
</Head>
The problem is that in the layout on the Nav element: Type '{ title: string | undefined; }' is not assignable to type 'string'. I understand and see what the problem is, but I don't know how to do things differently to make TS happy. In case I'm not being clear about what I want to end up with: I want a reusable Layout to wrap pages around. This Layout may or may not at times be given a title prop that sets the title for the tab
3 replies