Name | Progress |
---|---|
Introduction | Not Read |
π° Player | Not Read |
Name | Progress |
---|---|
Software Installation | Not Read |
Project Setup | Not Read |
Running and Testing | Not Read |
React and ReactDOM | Not Read |
π‘ Assignment 1: Welcome Message | Not Attempted |
Submissions | Not Read |
Name | Progress |
---|---|
JSX and Components | Not Read |
Props | Not Read |
πΎ Exercise: Props | Not Attempted |
CSS Styles | Not Read |
useState and Hooks | Not Read |
πΎ Exercise: useState | Not Attempted |
Conditional Rendering | Not Read |
Lists | Not Read |
πΎ Exercise: Lists | Not Attempted |
Forms and Events | Not Read |
πΎ Exercise: Forms | Not Attempted |
π‘ Assignment 2: Front End | Not Attempted |
Name | Progress |
---|---|
Pure Components - memo | Not Read |
Lifecycle - useEffect | Not Read |
Expensive? - useMemo | Not Read |
DOM Interactions - useRef | Not Read |
forwardRef | Not Read |
useImperativeHandle | Not Read |
πΎ useImperativeHandle | Not Attempted |
Context | Not Read |
useCallback | Not Read |
useId | Not Read |
useReducer | Not Read |
Name | Progress |
---|---|
Database | Not Read |
NextAuth and Github Authentication | Not Read |
Prisma and ORM | Not Read |
Project Setup | Not Read |
Project Authentication | Not Read |
Name | Progress |
---|---|
APIs | Not Read |
APIs - Slides | Not Attempted |
Rest APIs | Not Read |
Rest APIs - Express.js | Not Read |
ReastAPIs - Next.js | Not Read |
Securing APIs | Not Read |
Securing APIs - NextAuth | Not Read |
While server rendering is amazing, there are times when you will need to call a tRPC procedure from the client. There might be several reasons for that:
Let's explore how we can use RPC on the client.
In this part, we will transform our src/components/task-list.tsx server component into a client component. Then, we will implement and use a new mutation on the client as well.
The client components contain βuse clientβ statement at the top of the file. Please add this statement to the src/components/task-list.tsx file and reload your page
"use client";
import { CreateTask } from "~/components/create-task";
...
Oh, Oh! A daunting error appears in your browser:
We mentioned previously that asynchronous server components cannot be used client-side. Unfortunately, we cannot just remove the async statement from the component as we are using an asynchronous API call within it. Therefore, we need to remove all asynchronous calls. Also, we need to remove the server version of trpc api with react version, please adjust the following:
import { api } from "~/trpc/react"; // <- replaced server api with react api
import { useSession } from "next-auth/react";
export function TaskList() {
const session = useSession();
const tasksQuery = api.tasks.tasks.useQuery(undefined, {
enabled: !!session.data,
})
if (tasksQuery.isLoading) {
return <div>Loading tasks...</div>;
}
const tasks = tasksQuery.data ?? [];
Woooow, a lot of things happened here!
Try to refresh your page. Another oh oh! You receieve an error:
Error: [next-auth]: `useSession` must be wrapped in a <SessionProvider />
React uses Context Providers to pass data to any child without needing to pass it explicitly via props. This allows any react component access, for example, signed-in user data or a tRPC API structure. Therefore, we need to add these providers to our application. We have prepared the SessionProvider and TRPCReactProvider for you in the src/app/providers.tsx file (open it and check it ou!). To use it, please modify the src/app/layout.tsx file as below:
import { Providers } from "./providers";
...
export default function RootLayout({
children
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={inter.className}>
<Providers>{children}</Providers>
</body>
</html>
);
}
Please refresh you page and see the magic happening ;)
Mutations will likely be executed from client components only, as they require data coming from user interactions. While React provides a very neat way of calling server functions directly, we still prefer to use tRPC for better control and enforce type validation using the zod library.
Here is an example of calling a tRPC mutation in the src/components/crate-task.tsx file. Please go line by line in the file to see if you understand.
"use client";
import { useQueryClient } from "@tanstack/react-query";
import { getQueryKey } from "@trpc/react-query";
import { useState } from "react";
import { api } from "~/trpc/react";
import styles from "./create-task.module.css";
import { type Task } from "./task-list";
// import { useRouter } from 'next/navigation';
export function CreateTask() {
const [text, setText] = useState("");
// this is the new mutation
const createTask = api.tasks.addTask.useMutation();
// we use the query client to update the data in the caches
const queryClient = useQueryClient();
// not used now, but would be used if you loaded the data using a server component
// const router = useRouter();
return (
<>
<input
type="text"
value={text}
placeholder="What needs to be done?"
className={styles.taskInput}
onChange={(e) => setText(e.target.value)}
/>
<button
disabled={createTask.isPending}
className={styles.taskButton}
onClick={() => {
// call the mutation
createTask.mutate(
{
task: text
},
{
onSuccess(data) {
// update the cache on the client
// 1. find the key by which the data is identified ion the cache
const key = getQueryKey(api.tasks.tasks, undefined, "query");
// 2. read the data in the cache
const existing = queryClient.getQueryData<Task[]>(key) ?? [];
// 3. write the new data to the cache
queryClient.setQueryData(key, [...existing, data]);
/*
* if you use Server Component to get your data, you do
* not need to worry about this cache, but call
* router.refresh() instead
*/
}
}
);
}}
>
{createTask.isPending ? "Saving" : "Add Task"}
</button>
</>
);
}