diff --git a/.gitignore b/.gitignore index 6c5280a..cc9c178 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ tsconfig.node.tsbuildinfo /blob-report/ /playwright/.cache/ tsconfig.app.tsbuildinfo +codealike.json diff --git a/docs/TANSTACK-QUERY.md b/docs/TANSTACK-QUERY.md new file mode 100644 index 0000000..d18e226 --- /dev/null +++ b/docs/TANSTACK-QUERY.md @@ -0,0 +1,32 @@ +# tips + +- prefer `useSuspenseQuery` over `useQuery` +- prefer defining `queryOptions` over inlinignthem into the query hooks + + ```tsx + import { queryOptions,useSuspenseQuery } from "@tanstack/react-query"; + //users/queryOptions.ts + // this is re-usable and decltters your components + export const userQueryOptions = queryOptions({ + queryKey: ["user"], + queryFn: () => { + ... + } + }) + // users.tsx + const query = useSuspenseQuery(userQueryOptions); + ``` +- wrap the data fetching components with `Suspense` component + + ```tsx + // users page +
+
Users page + Loading users
}> + + + + ``` + +run `p/mpm run page users` to scafold a page with these best practices + diff --git a/docs/TANSTACK-ROUTER.md b/docs/TANSTACK-ROUTER.md new file mode 100644 index 0000000..81b583f --- /dev/null +++ b/docs/TANSTACK-ROUTER.md @@ -0,0 +1,108 @@ +- anything under the src/routes folder is a route + +ex + +- `src/routes/index.tsx` ->` /` +- `src/routes/profile.tsx` or `src/routes/profile/index.tsx` -> `/profile/` + +Dynamic routes + +- `src/routes/users/$oneuser/index.tsx` -> `/users/$oneuser` + +inside here you'll have access to the `oneuser` param + +```tsx +// src/routes/users/$user/index.tsx +import { createFileRoute, useParams } from '@tanstack/react-router' + +export const Route = createFileRoute('/users/$user')({ + component:OneUserComponent, +}) +functon OneUserComponent() { +const {user} = useParams({ + from:"/users/$user" +}) + return ( +
+

{user}

+
+ ) +} +``` + +if you nest multiple dynamic routes then you can access them in the same way + +```tsx +// src/routes/users/$user/friends/$friend/index.tsx +import { createFileRoute, useParams } from '@tanstack/react-router' + +export const Route = createFileRoute('/users/$user/friends/$friend/')({ + component: RouteComponent, +}) + +function RouteComponent() { + const { friend,user } = useParams({ + from: "/users/$user/friends/$friend/", + }); + return ( +
+

{user}

+

{friend}

+
+ ); +} + + +``` + +you can also define search params ,validate them and auth guard + +```tsx +import { + createFileRoute, + redirect, + useNavigate, + useSearch, +} from "@tanstack/react-router"; +import { z } from "zod"; +const searchparams = z.object({ + // make it optional if it won't always be used + page: z.number().optional(), +}); + +export const Route = createFileRoute("/users/")({ + component: RouteComponent, + // declare and validate your search params here + // this page should alwatys have /users?page=1 + validateSearch: (search) => searchparams.parse(search), + // this is how you auth guard routes (only allow logged in users here ) + async beforeLoad(ctx) { + const viewer = ctx.context?.viewer; + if (!viewer?.record) { + throw redirect({ + to: "/auth", + // this search params will be used to redirect you back to this page once you log in + search: { returnTo: ctx.location.pathname }, + }); + } + }, +}); + +function RouteComponent() { + const { page } = useSearch({ + from: "/users/", + }); + const navigate = useNavigate({ + from: "/users", + }); + return ( +
+ {page} + +
+ ); +} + +``` diff --git a/docs/TESTING.md b/docs/TESTING.md index dd06592..8498bd1 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -1,5 +1,11 @@ # Testing +>[!NOTE] +> Prefer e2e (playwright) fro testing the ui instead of unit tests. and uase the tooling like recording of tests and locators. +> use unit tests for units of logic and functions only + + + ```sh npm run test ```