Skip to content
This repository has been archived by the owner on Aug 5, 2024. It is now read-only.

Commit

Permalink
React v4 Migration (#547)
Browse files Browse the repository at this point in the history
* Update

* Update
  • Loading branch information
kien-ngo authored Aug 1, 2024
1 parent bc3e8ca commit ce404f1
Show file tree
Hide file tree
Showing 6 changed files with 409 additions and 38 deletions.
32 changes: 32 additions & 0 deletions src/app/react/v5/migrate/cheatsheet/page.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
### React Cheatsheet

| Task | `@thirdweb-dev/react` | `thirdweb` |
| ---------------------| ----------------------------------------------------- | --------------------------------------------------- |
| Provider | `import { ThirdwebProvider} from @thirdweb-dev/react` | [`import { ThirdwebProvider } from "thirdweb/react"`](/react/v5/ThirdwebProvider) |
| Contract | `useContract(...)` | [`getContract(...) // not a hook`](/references/typescript/v5/getContract) |
| Address | `useAddress(...)` | [`useActiveAccount(...) // account?.address`](/references/typescript/v5/useActiveAccount) |
| Read | `useContractRead(...)` | [`useReadContract(...)`](/references/typescript/v5/useReadContract) |
| Write | `useContractWrite(...)` | [`useSendTransaction()`](/references/typescript/v5/useSendTransaction) |
| Extensions | `useNFTs(...)` | [`useReadContract(getNFTs, { ... })`](/references/typescript/v5/useReadContract) |
| Get Signer | `useSigner()` | [`useActiveAccount()`](/references/typescript/v5/useActiveAccount) |
| Get Wallet | `useWallet()` | [`useActiveWallet()`](/references/typescript/v5/useActiveWallet) |
| Button | `Web3Button` | [`TransactionButton`](/react/v5/TransactionButton) |
| Connect | `ConnectWallet` | [`ConnectButton`](/react/v5/ConnectButton) |
| Connection Status | `useConnectionStatus()` | [`useActiveWalletConnectionStatus()`](/references/typescript/v5/useActiveWalletConnectionStatus) |
| Switch Chain | `useSwitchChain()` | [`useSwitchActiveWalletChain()`](/references/typescript/v5/useSwitchActiveWalletChain) |
| Get Connected Chain | `useChain()` | [`useSwitchActiveWalletChain()`](/references/typescript/v5/useSwitchActiveWalletChain) |


### TypeScript Cheatsheet

| Task | `@thirdweb-dev/sdk` | `thirdweb` |
| ---------- | -------------------------------------------------------- | ------------------------------------------------- |
| Chains | `import { Sepolia } from "@thirdweb-dev/chains"` | [`import { sepolia } from "thirdweb/chains"`](/typescript/v5/chain) |
| Wallets | `import { MetaMaskWallet } from "@thirdweb-dev/wallets"` | [`import { createWallet } from "thirdweb/wallets"`](/references/typescript/v5/createWallet) |
| Initialize | `new ThirdwebSDK(...)` | [`createThirdwebClient({ ... })`](/references/typescript/v5/createThirdwebClient) |
| Contract | `await sdk.getContract(...)` | [`getContract(...) // no await`](/references/typescript/v5/getContract) |
| Read | `await contract.call(...)` | [`await readContract(...)`](/references/typescript/v5/readContract) |
| Prepare | `await contract.prepare(...)` | [`prepareContractCall(...) // no await`](/references/typescript/v5/prepareContractCall) |
| Send | `await contract.call(...)` | [`await sendTransaction(...)`](/references/typescript/v5/sendTransaction) |
| Extensions | `await contract.erc721.getAll()` | [`await getNFTs(...)`](/references/typescript/v5/erc721/getNFTs) |
| Deploy | `sdk.deployer.deployBuiltInContract(...)` | [`await deployPublishedContract(...)`](/references/typescript/v5/deploy/deployPublishedContract) |
172 changes: 172 additions & 0 deletions src/app/react/v5/migrate/contracts/page.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
[Migrate from React v4](/react/v5/migrate)

# Interacting with contracts

With SDK v4, you always have to "load" a contract with `useContract`. This process adds complexity to your app and inpacts its performance.
In the latest version, a smart contract (type: [`ThirdwebContract`](/references/typescript/v5/ThirdwebContract)) represents a simple object containing info about the contract address, the chain it was deployed on, and the thirdweb client object.

Example for declaring a smart contract on Ethereum mainnet
```tsx
import { getContract, createThirdwebClient } from "thirdweb";
import { ethereum } from "thirdweb/chains";

const client = createThirdwebClient({
clientId: process.env.NEXT_PUBLIC_TW_CLIENT_ID,
});

const contract = getContract({
address: "0x....",
chain: ethereum,
client,
});
```

## Contract extensions

This is a new terminology that we introduced in the new SDK. Basically, each extension represents a method of a contract, be it a "write" or a "read" method.

An extension is a function that returns a [`PreparedTransaction`](/references/typescript/v5/PreparedTransaction) which in turn can be executed in a React hook for interacting with the contract. We will talk more about it in the section below.

One of the amazing updates that v5 brings is the rich set of prebuilt extensions. They are the contract methods that have been precompile to ensure a typesafe & performant developer experience.

Check out the list of over 100 prebuilt extensions [here](/typescript/v5/extensions/built-in), ranging from ERC20, ERC721, ERC1155 to top popular DeFi protocols like Uniswap, Farcaster & Lens.

Example: Import an ERC1155 "read" extension, for checking the balance of a wallet
```tsx
import { balanceOf } from "thirdweb/extension/erc1155";

const transaction = balanceOf({
contract,
owner: "0x...",
tokenId: 0n,
});
```

## Reading states of a contract
Given the task of calling `balanceOf` from an ERC1155 contract, we'll be comparing the code between v4 and v5

#### SDK v4
```tsx
import { useNFTBalance, useContract } from "@thirdweb-dev/react";

function App() {
const { contract } = useContract(contractAddress);
const { isLoading, data, error } = useNFTBalance(
contract,
"{{wallet_address}}",
"{{token_id}}",
);
}

```

#### SDK v5
```tsx
import { getContract, createThirdwebClient } from "thirdweb";
import { balanceOf } from "thirdweb/extensions/erc1155";
import { ethereum } from "thirdweb/chains";
import { client } from "@lib/client";

const contract = getContract({
address: "0x....",
chain: ethereum,
client,
});

function App() {
const { data } = useReadContract(balanceOf, { contract, owner: "0x...", tokenId: 0n });
}
```

As you can see from the example above, we introduced the hook [`useReadContract`](/references/typescript/v5/useReadContract) in v5.
You should use it to perform any contract "read" in your React app.
It is the perfect replacement for the old chunky React hooks from v4.

The formula for reading a contract state is:
```
useReadContract + <the read contract method>
```

#### If the extension you are looking for is not included in the SDK
You can always use the function signature with `useReadContract` (It's also typesafe)
```tsx
useReadContract({
contract,
method: "function balanceOf(address _owner, uint256 tokenId) view returns (uint256)",
...
})
```

#### Tips for getting a function's signature
Go to the thirdweb Dashboard's explorer page and select the function that you want to interact with.
You should see the "Use this function in your app" section with the code snippet for the signature of the function.

[An example](https://thirdweb.com/avalanche-fuji/0xd5e815241882676F772A624E3892b27Ff3a449c4/explorer?name=balanceOf)


## Writing to a contract
In v5, you can utilize the following hooks for writing to contracts: [`useSendTransaction`](/references/typescript/v5/useSendTransaction) and [`useSendAndConfirmTransaction`](/references/typescript/v5/useSendAndConfirmTransaction).
The main difference between the 2 hooks is that `useSendTransaction` will mark the request as "complete" once the transaction is sent,
while `useSendAndConfirmTransaction` will wait until the transaction is included in the blockchain.

Given the task of claiming an NFT from an NFT Drop collection, let's compare the code between the SDK v4 and v5


#### SDK V4
```tsx
import { useContract, useClaimNFT } from "@thirdweb-dev/react";

function App() {
const { contract } = useContract(contractAddress);
const {
mutateAsync: claimNft,
isLoading,
error,
} = useClaimNFT(contract);

return (
<Web3Button
contractAddress={contractAddress}
action={() =>
claimNft({
to: "{{wallet_address}}", // Use useAddress hook to get current wallet address
quantity: 1,
})
}
>
Claim NFT
</Web3Button>
);
}
```

#### SDK v5
```tsx
import { useSendTransaction } from "thirdweb/react";
import { claimTo } from "thirdweb/extension/erc721";

function App() {
const transaction = claimTo({ contract, quantity: 1n, to: "0x..." });
const { mutateAsync: claimNft } = useSendTransaction();

return <button onClick={() => claimNft(transaction)}>
Claim
</button>
}
```

Another beautiful thing about the SDK v5 is that it comes with the [`TransactionButton`](/references/typescript/v5/TransactionButton)
which allows you to make a contract call _without_ having to use the above React hooks. As you can see, the code is much cleaner this way!

```tsx
import { TransactionButton } from "thirdweb/react";
import { claimTo } from "thirdweb/extension/erc721";

function App() {
return <TransactionButton transaction={
() => claimTo({ contract, quantity: 1n, to: "0x..." })
}>
Claim
</TransactionButton>
}
```
112 changes: 112 additions & 0 deletions src/app/react/v5/migrate/installation/page.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import {
ArticleCard,
GithubTemplateCard,
Grid,
ExpandableGrid,
createMetadata,
OpenSourceCard,
Stack,
Steps,
Step,
InstallTabs,
Callout
} from "@doc";

[Migrate from React v4](/react/v5/migrate)

# Installation & Setups

Welcome to the migration guide for updating your React SDK from version 4 to version 5. This guide will walk you through the necessary steps to ensure a smooth transition. In this section, we'll cover the installation process for the new version of the SDK.

## Installation

#### Below is how you install thirdweb v4 SDKs
<InstallTabs
npm="npm i @thirdweb-dev/sdk @thirdweb-dev/react [email protected]"
yarn="yarn add @thirdweb-dev/sdk @thirdweb-dev/react [email protected]"
pnpm="pnpm i @thirdweb-dev/sdk @thirdweb-dev/react [email protected]"
bun="bun i @thirdweb-dev/sdk @thirdweb-dev/react [email protected]"
/>

#### With the latest version, everything comes in one single package
<InstallTabs
npm="npm i thirdweb"
yarn="yarn add thirdweb"
pnpm="pnpm i thirdweb"
bun="bun i thirdweb"
/>


## Setups

Once you have installed the latest package (alongside the older version that you want to replace), you can start the migration process.

### ThirdwebProvider

In the latest SDK, the [`ThirdwebProvider`](/references/typescript/v5/ThirdwebProvider) no longer accepts any prop such as `activeChain`, `clientId` or any extra SDK options.
Instead, you only need to pass the clientId when necessary (we'll talk more about this in a few sections below).

```tsx
import { ThirdwebProvider } from "thirdweb/react";

<ThirdwebProvider>
...
</ThirdwebProvider>
```

###### Progressive migration


If you're currently using the `@thirdweb-dev/sdk`, you can progressively migrate to the new `thirdweb` SDK. Both SDKs can be used side by side and are interoperable with each other.

In React, you can mix and match the v4 and v5 `ThirdwebProvider`, that gives you access to the hooks and functionality of both SDKs.
This way, once you have moved away from all the v4 functionalities, you can finally remove the `ThirdwebProviderV4` from your app.

```tsx
import { ThirdwebProvider as ThirdwebProviderV4 } from "@thirdweb-dev/react";
import { ThirdwebProvider } from "thirdweb/react"; // v5

<ThirdwebProviderV4 activeChain={...} clientId={...}>
<ThirdwebProvider>
...
</ThirdwebProvider>
</ThirdwebProviderV4>
```

### Connecting wallets

Similar to v4's `ConnectWallet` component, the latest version has the [`ConnectButton`](/connect/sign-in/ConnectButton) component which has the same functionality.

However, unlike with v4 where the number of supported wallets is limited (about 20), and adding more wallets mean your app becomes heavier,
the SDK v5 supports [over 300 wallets](/typescript/v5/supported-wallets) with virtually no impact to your application.

Here's how you use the new `ConnectButton`:

```tsx
import { createThirdwebClient } from "thirdweb";
import { ConnectButton } from "thirdweb/react";

const client = createThirdwebClient({
clientId: process.env.NEXT_PUBLIC_TW_CLIENT_ID,
});

<ConnectButton client={client} />
```

To learn more about the new `ConnectButton`, head over to the [Playground](https://thirdweb.com/dashboard/connect/playground).

Notice how you are passing the thirdweb client to the component itself and not to the `ThirdwebProvider` like in v4?
By not putting every config inside the context wrapper, we were able to make the SDK v5 much more lightweight since you only load what you need!


Tip: You can reuse the thirdweb client object by putting it in a file and export it.
```ts
// @lib/client.ts

import { createThirdwebClient } from "thirdweb";

export const client = createThirdwebClient({
clientId: process.env.NEXT_PUBLIC_TW_CLIENT_ID,
});

```
Loading

0 comments on commit ce404f1

Please sign in to comment.