Skip to content

Commit

Permalink
refactor: migrate BuildersCheckInCount to Server Component
Browse files Browse the repository at this point in the history
- Remove client-side hooks in favor of viem's createPublicClient
- Implement contract reading directly on server
- Eliminate loading states thanks to SSR
- Reduce client-side JavaScript bundle
  • Loading branch information
All-Khwarizmi committed Jan 11, 2025
1 parent 9a7e113 commit 9fb74d4
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 48 deletions.
49 changes: 33 additions & 16 deletions packages/nextjs/app/_components/BuildersCheckInCount.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,41 @@
"use client";

import React from "react";
import { CounterDisplay } from "./CounterDisplay";
import { useScaffoldReadContract } from "~~/hooks/scaffold-eth";
import { createPublicClient, getContract, http } from "viem";
import { optimism } from "viem/chains";

const CONTRACT_NAME = "BatchRegistry";
const CONTRACT_ADR = "0x72ccAbE6620fa94eC69569d17f18a3914BEFBFD6";
const FUNCTION_NAME = "checkedInCounter";

function BuildersCheckInCount() {
// Get the result of the target function call from the deployed contract
const {
data: counter,
isLoading,
error,
} = useScaffoldReadContract({
contractName: CONTRACT_NAME,
functionName: FUNCTION_NAME,
});
// Defining the ABI for just the function we need
const BatchRegistryABI = [
{
name: FUNCTION_NAME,
type: "function",
stateMutability: "view",
inputs: [],
outputs: [{ type: "uint256" }],
},
] as const;

async function BuildersCheckInCount() {
try {
// A Client in the context of viem is similar to an Ethers.js Provider.
const publicClient = createPublicClient({
chain: optimism,
transport: http(),
});

const contract = getContract({
address: CONTRACT_ADR,
abi: BatchRegistryABI,
client: publicClient,
});

const counter = await contract.read.checkedInCounter();

return <CounterDisplay data={counter} isLoading={isLoading} error={error} />;
return <CounterDisplay data={counter} error={null} />;
} catch (error) {
return <CounterDisplay data={undefined} error={error instanceof Error ? error : new Error("Unknown error")} />;
}
}

export default BuildersCheckInCount;
24 changes: 5 additions & 19 deletions packages/nextjs/app/_components/CounterDisplay.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,11 @@
import { displayTxResult } from "../debug/_components/contract";
import { ArrowPathIcon } from "@heroicons/react/16/solid";

export async function CounterDisplay({
data: counter,
isLoading,
error,
}: {
data?: bigint;
isLoading: boolean;
error: Error | null;
}) {
export async function CounterDisplay({ data: counter, error }: { data?: bigint; error: Error | null }) {
return (
<div className="text-lg flex gap-2 justify-center items-center">
<span className="font-bold">Checked in builders count:</span>
{isLoading || (!error && !counter) ? (
<ArrowPathIcon className="size-5 animate-spin" />
) : error ? (
<span className="text-error">Error!</span>
) : (
<span>{displayTxResult(counter)}</span>
)}

{error && <span className="text-error">Error!</span>}

{counter && <span>{counter.toString()}</span>}
</div>
);
}
15 changes: 2 additions & 13 deletions packages/nextjs/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Suspense } from "react";
import Link from "next/link";
import BuildersCheckInCount from "./_components/BuildersCheckInCount";
import type { NextPage } from "next";
import { ArrowPathIcon, BugAntIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline";
import { BugAntIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline";

const Home: NextPage = () => {
return (
Expand All @@ -14,9 +13,7 @@ const Home: NextPage = () => {
<span className="block text-4xl font-bold">Batch 12</span>
</h1>
<p className="text-center text-lg">Get started by taking a look at your batch GitHub repository.</p>
<Suspense fallback={<LoadingCounter />}>
<BuildersCheckInCount />
</Suspense>
<BuildersCheckInCount />
</div>

<div className="flex-grow bg-base-300 w-full mt-16 px-8 py-12">
Expand Down Expand Up @@ -49,11 +46,3 @@ const Home: NextPage = () => {
};

export default Home;
function LoadingCounter() {
return (
<div className="text-lg flex gap-2 justify-center items-center">
<span className="font-bold">Checked in builders count:</span>
<ArrowPathIcon className="size-5 animate-spin" />
</div>
);
}

0 comments on commit 9fb74d4

Please sign in to comment.