lesson-1_UIをアップグレードしよう
💫 UI の仕上げ
NFTキャラクターをMintしたり、ボスのデータを取得したりするときに、ローディングマークをUIに表示していきましょう。
これから、下記のケースにローディングマーク実装していきます。
1. App.js
: ユーザーがNFTキ ャラクターを持っているかフロントエンドが確認している状況
2. SelectCharacter
コンポーネント : ユーザーがNFTキャラクターをMintするのをフロントエンドが待機している状況
3. Arena
コンポーネント : 攻撃が終了するのをフロントエンドが待機している状況
client/src/Components
フォルダにLoadingIndicator
コンポーネントが格納されています。
このレッスンでは、このLoadingIndicator
コンポーネントを使っていきます。
🔁 App.js
にローディングマークを追加する
1つ目のケース、「ユーザーがNFTキャラクターを持っているかフロントエンドが確認している状況」で、Webアプリケーションにローディングマークを表示していきましょう。
まず、App.js
を開き、const [characterNFT, setCharacterNFT] = useState(null);
の直下に下記を追加しましょう。
// ロード状態を初期化します。
const [isLoading, setIsLoading] = useState(false);
次に、コントラクトからcheckIfUserHasNFT
関数を呼び出すなど、非同期操作を実行している際に、ロード状態を設定する実装を行います。
setIsLoading(true);
を、下記2つのuseEffects
に追加しましょう。
// ページがロードされたときに useEffect()内の関数が呼び出されます。
useEffect(() => {
// ページがロードされたら、即座にロード状態を設定するようにします。
setIsLoading(true);
checkIfWalletIsConnected();
}, []);
// ページがロードされたときに useEffect()内の関数が呼び出されます。
useEffect(() => {
// スマートコントラクトを呼び出す関数です。
const fetchNFTMetadata = async () => {
console.log("Checking for Character NFT on address:", currentAccount);
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const gameContract = new ethers.Contract(
CONTRACT_ADDRESS,
myEpicGame.abi,
signer
);
const txn = await gameContract.checkIfUserHasNFT();
if (txn.name) {
console.log("User has character NFT");
setCharacterNFT(transformCharacterData(txn));
} else {
console.log("No character NFT found");
}
// ユーザーが保持している NFT の確認が完了したら、ロード状態を false に設定します。
setIsLoading(false);
};
if (currentAccount) {
console.log("CurrentAccount:", currentAccount);
fetchNFTMetadata();
}
}, [currentAccount]);
次に、App.js
の先頭に下記を追加して、LoadingIndicator
をインポートしてください。
import LoadingIndicator from "./Components/LoadingIndicator";
次に、renderContent
関数の先頭に、下記を追加しましょう。
// アプリがロード中の場合は、LoadingIndicator をレンダリングします。
if (isLoading) {
return <LoadingIndicator />;
}
この処理により、Webアプリケーションがコントラクトからデータを読み込んでいる間は、ローディングマークが表示されます。
次に、checkIfWalletIsConnected
に下記のように更新して、フロントエンドがユーザーがMetaMaskを持っているか確認している際に、ローディングマークを表示させましょう。
// ユーザーが MetaMask を持っているか確認します。
const checkIfWalletIsConnected = async () => {
try {
const { ethereum } = window;
if (!ethereum) {
console.log("Make sure you have MetaMask!");
// 次の行で return を使用するため、ここで isLoading を設定します。
setIsLoading(false);
return;
} else {
console.log("We have the ethereum object", ethereum);
// accounts にWEBサイトを訪れたユーザーのウォレットアカウントを格納します。
// (複数持っている場合も加味、よって account's' と変数を定義している)
const accounts = await ethereum.request({ method: "eth_accounts" });
// もしアカウントが一つでも存在したら、以下を実行。
if (accounts.length !== 0) {
// account という変数にユーザーの1つ目(= Javascript でいう0番目)のアドレスを格納
const account = accounts[0];
console.log("Found an authorized account:", account);
// currentAccount にユーザーのアカウントアドレスを格納
setCurrentAccount(account);
} else {
console.log("No authorized account found");
}
}
} catch (error) {
console.log(error);
}
//すべての関数ロジックの後に、state プロパティを解放します。
setIsLoading(false);
};
ウォレットの接続を解除すると、ローディングマークが表示されるはずです。ウォレット接続ボタンが表示されるように、isLoading
状態のプロパティを解放する(=false
にする)必要があります。
🔁 SelectCharacter
コンポーネントにローディングマークを追加する
2つ目のケース、「ユーザーがNFTキャラクターをMintするのをフロントエンドが待機している状況」で、Webアプリケーションにローディングマークを表示していきましょう。
まず、client/src/Components/SelectCharacter/index.js
の先頭に、下記を追加しましょう。
import LoadingIndicator from "../../Components/LoadingIndicator";
次に、SelectCharacter/index.js
の中に記載されたconst [gameContract, setGameContract] = useState(null);
の直下に、const [mintingCharacter, setMintingCharacter] = useState(false);
を追加しましょう。
- 下記を参照してください。
//NFT キャラクターのメタデータを保存する状態変数を初期化します。
const [characters, setCharacters] = useState([]);
// コントラクトのデータを保有する状態変数を初期化します。
const [gameContract, setGameContract] = useState(null);
// Minting の状態保存する状態変数を初期化します。
const [mintingCharacter, setMintingCharacter] = useState(false);
ここでは、App.js
でisLoading