Skip to content

sadfrogstudying/internationalstudyspots

Repository files navigation

Notes

Get TRPC router outputs

import { type RouterOutputs } from "@/trpc/shared";
type StudySpotAll = RouterOutputs["studySpot"]["getAll"];

Get the type of a prop in a React component in TypeScript

import CustomComponent from "component-library";
import type { ComponentProps } from "react";

type PropType = ComponentProps<typeof CustomComponent>["propName"];

Get Prisma model type

import { type StudySpot } from "@prisma/client";

const studySpots: StudySpot[] = [];

Wrapping/Mirroring a HTML Element

// implementation
export interface ButtonProps extends React.ComponentPropsWithoutRef<"button"> {
  specialProp?: string;
}
export function Button(props: ButtonProps) {
  const { specialProp, ...rest } = props;
  // do something with specialProp
  return <button {...rest} />;
}

Infer type from zod schema

const spotBooleanSchema = z.object({
  powerOutlets: z.boolean(),
  wifi: z.boolean(),
});

type A = z.infer<typeof spotBooleanSchema>;

Prisma - filtering with where and OR

const spots = await findManyHandler(ctx.db, {
  ...(cursor && { skip: 1, cursor: { id: cursor } }),
  ...(where && {
    where: {
      where.powerOutlets: true,
      OR: [
        {
          country: {
            equals: "Australia",
          },
        },
        { country: { equals: "Japan" } },
      ],
    },
  }),
});

Infer type from TRPC router - @trpc/server exports the following helper types to assist with inferring these types from the AppRouter exported by your @trpc/server router (docs):

inferRouterInputs inferRouterOutputs

// @filename: client.ts
import type { inferRouterInputs, inferRouterOutputs } from "@trpc/server";
import type { AppRouter } from "./server";

type RouterInput = inferRouterInputs<AppRouter>;
type RouterOutput = inferRouterOutputs<AppRouter>;

type PostCreateInput = RouterInput["post"]["create"];

type PostCreateInput = {
  title: string;
  text: string;
};
type PostCreateOutput = RouterOutput["post"]["create"];

Caching

unstable_cache works to cache functions.

Testing dev API route changes on Mobile

ngrok allows us to put localhost on the internet so we can test the mobile app against the development backend. Install instructions here

Run:

ngrok http 3000

In the terminal, the URL should be under Forwarding.

You can now fire requests to: https://8e3b-49-255-185-210.ngrok-free.app/ and https://8e3b-49-255-185-210.ngrok-free.app/api/studyspots.getall.

Pattern

In nested components that use data from the same query, can either call the useQuery hook to get the value in every component to save from passing props to multiple components.

const { data, isLoading } = api.user.currentBySession.useQuery(undefined);

But can get into an infinite loop if you're conditionally rendering child component, as it will refetch on mount.

const { data, isLoading } = api.user.currentBySession.useQuery(undefined, {
  refetchOnMount: false,
});

I decided to just pass the data as props to children as remembering to add refetchOnMount is error prone.

type User = RouterOutputs["user"]["currentBySession"];

export default function Navigation({ user }: { user: User | undefined }) {
  // ...
}

Loops

Careful of returning in different loops. In for..of, return will stop the loop entirely, use continue if you just want to go to next cycle.

Brittle tests caused by React Dropzone

The combination of react hook form, react dropzone and image browser compression, with value transformations makes for extremely brittle tests. Changing to dropzone component from react aria by Adobe as it's better maintained.

Useful Links

When making new Github Action jobs

Update branch protection rule and add the new job (https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/managing-a-branch-protection-rule#creating-a-branch-protection-rule).

About

Updated with integration tests

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published