メインコンテンツまでスキップ

lesson-3_WebサイトにGIFを表示しよう!

🧪 テストデータを表示する

最終的には、ユーザーがWebアプリケーションにPhantom Walletを接続している場合のみ、Solanaチェーン上に保存されたGIFデータを表示していきます。

ですが、今はSolanaプログラムと連携する前段階ということで、WebアプリケーションにGIFのテストデータを表示していきます。

テストデータは好きなものを使用していただいて構いません。

今回の例ではGIF画像のシェアサービスGIPHYを利用していきます。

GIPHYで気に入った画像を選択したら、Shareをクリックし、Copy GIF Linkボタンを押してリンクをコピーしておきます。

GIPHY

それでは、お気に入りのGIF画像へのリンクをApp.jsに反映させましょう。

App.jsの定数を宣言している場所に下記を追加します。

const TEST_GIFS = [
"https://media.giphy.com/media/ZqlvCTNHpqrio/giphy.gif",
"https://media.giphy.com/media/bC9czlgCMtw4cj8RgH/giphy.gif",
"https://media.giphy.com/media/kC8N6DPOkbqWTxkNTe/giphy.gif",
"https://media.giphy.com/media/26n6Gx9moCgs1pUuk/giphy.gif",
];

テストデータで使用するGIFは何枚でもOKです。

また、使用するGIFにあわせ、以下のようにWebサイトのタイトルと説明を変更しておきましょう。

<p className="header">🖼 GIF Portal</p>
<p className="sub-text">
View your GIF collection ✨
</p>

続いて、設定したGIFをWebアプリケーションに表示します。

アプローチとしてはrenderNotConnectedContainer関数と同じ方法をとります。

それではrenderNotConnectedContainer関数のすぐ下に、以下のとおりrenderConnectedContainer関数を追加しましょう。

const renderConnectedContainer = () => (
<div className="connected-container">
<div className="gif-grid">
{TEST_GIFS.map((gif) => (
<div className="gif-item" key={gif}>
<img src={gif} alt={gif} />
</div>
))}
</div>
</div>
);

renderConnectedContainer関数には、すべてのGIFをレンダリングするコードが書かれています。

ただし、これだけではWebアプリケーションの表示は変わりません。

renderConnectedContainer 関数もrenderNotConnectedContainer関数と同じように、呼び出す必要があります。

return文の中身を以下のとおり変更します。

return (
<div className="App">
<div className="container">
<div className="header-container">
<p className="header">🖼 GIF Portal</p>
<p className="sub-text">View your GIF collection ✨</p>
{!walletAddress && renderNotConnectedContainer()}
</div>
<main className="main">
{/* ウォレットが接続されている場合にrenderConnectedContainer関数を実行します。 */}
{walletAddress && renderConnectedContainer()}
</main>
<div className="footer-container">
<img alt="Twitter Logo" className="twitter-logo" src={twitterLogo} />
<a
className="footer-text"
href={TWITTER_LINK}
target="_blank"
rel="noreferrer"
>{`built on @${TWITTER_HANDLE}`}</a>
</div>
</div>
</div>
);

これらすべてを変更したうえでPhantom Walletを接続すると、設定したGIFが全て表示されているはずです。

GIF Portal

WebアプリケーションのスタイルはApp.cssで設定済みですが、好みに合わせて変更してみてください。

🔤 GIF 入力ボックスを作成する

さて、それではこれからWebアプリケーションにお気に入りのGIFを追加し、Solanaチェーン上に保存するための機能を追加していきましょう。

そのための準備として、まずはGIFのリンクを入力するエリアと送信ボタンを作成していきます。

なお、入力ボックスはユーザーがウォレットをアプリに接続したときにのみ表示されるようにします。

renderConnectedContainer関数を以下のように修正しましょう。

const renderConnectedContainer = () => (
<div className="connected-container">
<form
onSubmit={(event) => {
event.preventDefault();
}}
>
<input type="text" placeholder="Enter gif link!" />
<button type="submit" className="cta-button submit-gif-button">
Submit
</button>
</form>
<div className="gif-grid">
{TEST_GIFS.map((gif) => (
<div className="gif-item" key={gif}>
<img src={gif} alt={gif} />
</div>
))}
</div>
</div>
);

ブラウザを確認すると、入力ボックスと送信ボタンが追加されているはずです。

ただし、現段階では入力ボックスにGIFリンクを入力したり、Submitボタンを押したりしても何も起こりません。

これらの機能が正常に機能するよう、ロジックを記述していきましょう。

const [walletAddress, setWalletAddress] = useState(null);が記述されているすぐ下に以下のコードを追加します。

const [inputValue, setInputValue] = useState("");

これは、入力ボックス内に入力されたGIFリンクのstateを管理するためのものです。

GIFリンクはinputValueに設定され、管理されます。

続いて、connectWallet関数のすぐ下に以下のコードを追加します。

const onInputChange = (event) => {
const { value } = event.target;
setInputValue(value);
};

この関数では、入力ボックスに入力された値をinputValueに設定するだけの関数で、renderConnectedContainer関数で使用します。

続いて、renderConnectedContainer関数のinputタグの中身を以下のとおり変更しましょう。

<input
type="text"
placeholder="Enter gif link!"
value={inputValue}
onChange={onInputChange}
/>

ここまででSolanaプログラムへGIFリンクを送信する準備が整いました。

最後に、SolanaプログラムへGIFリンクを送信する関数を記述していきます。

onInputChange関数の下に以下のコードを追加します。

const sendGif = async () => {
if (inputValue.length > 0) {
console.log("Gif link:", inputValue);
} else {
console.log("Empty input. Try again.");
}
};

この関数は、あとでSolanaプログラムと接続するときに処理を追加します。

現段階では、入力ボックスへの値を判定し、値があればGIFリンクを、なければ入力を促すメッセージをコンソールに出力するだけの機能です。

なお、Solanaプログラムと接続するには非同期処理が必要になります。

Solanaプログラムとの接続中にWebアプリケーション側で他の処理が走ってしまうと思わぬエラーが引き起こされる可能性があるためです。

それでは最後に、sendGif関数を機能させるため、renderConnectedContainer関数のformタグを以下のとおり変更しましょう。

<form
onSubmit={(event) => {
event.preventDefault();
sendGif();
}}
>

それではブラウザ上でGIFリンクを入力してSubmitボタンを押してみましょう。

コンソールに入力したGIFリンクが表示されていればOKです。

🌈 GIF データの state を設定する

Solanaプログラムと接続する前に、もう1つ設定するものがあります。

それは、GIFリンクのフェッチです。

現状はTEST_GIFSで設定したGIFデータをレンダリングしていますが、このプロジェクトの処理フローは以下のようになります。

1. Webアプリを開く。

2. ウォレットを接続する。

3. SolanaプログラムからGIFリストを取得する。

上記を実装するためには、useStateを使用してgifList(GIFリンクの一覧)の状態を管理する必要があります。

それでは、他のuseState宣言をしたすぐ下にgifListの状態を管理するコードを以下のように追加しましょう。

const [walletAddress, setWalletAddress] = useState(null);
const [inputValue, setInputValue] = useState("");
const [gifList, setGifList] = useState([]);

次に、ユーザーがウォレットを接続した場合にのみGIFリストを取得できるよう、処理を追加します。

現段階ではTEST_GIFSにテストデータが設定されているので、TEST_GIFSを使ってSolanaプログラムからのフェッチをシミュレートしてみましょう。

既存のuseEffectのすぐ下に、フェッチ用のコードを追加します。

useEffect(() => {
const onLoad = async () => {
await checkIfWalletIsConnected();
};
window.addEventListener("load", onLoad);
return () => window.removeEventListener("load", onLoad);
}, []);

useEffect(() => {
if (walletAddress) {
console.log("Fetching GIF list...");

// Solana プログラムからのフェッチ処理をここに記述します。

// TEST_GIFSをgifListに設定します。
setGifList(TEST_GIFS);
}
}, [walletAddress]);

walletAddressが設定されている場合にのみフェッチ処理が実行され、GIFデータが設定されます。

今はテストデータを使用しているため、テストデータがgifListに設定されるだけの処理です。

それでは、設定されたgifListを利用するために、renderConnectedContainer関数を以下のとおり修正しましょう。

const renderConnectedContainer = () => (
<div className="connected-container">
<form
onSubmit={(event) => {
event.preventDefault();
sendGif();
}}
>
<input
type="text"
placeholder="Enter gif link!"
value={inputValue}
onChange={onInputChange}
/>
<button type="submit" className="cta-button submit-gif-button">
Submit
</button>
</form>
<div className="gif-grid">
{/* TEST_GIFSの代わりにgifListを使用します。 */}
{gifList.map((gif) => (
<div className="gif-item" key={gif}>
<img src={gif} alt={gif} />
</div>
))}
</div>
</div>
);

仕上げとして、入力フォームを送信すると、GIFがgifListに追加され、テキストフィールドがクリアされるようにしましょう。

sendGif関数を以下のとおり修正します。

const sendGif = async () => {
if (inputValue.length > 0) {
console.log("Gif link:", inputValue);
setGifList([...gifList, inputValue]);
setInputValue("");
} else {
console.log("Empty input. Try again.");
}
};

ここまででSolanaプログラムと接続するための準備が整いました。

🙋‍♂️ 質問する

ここまでの作業で何かわからないことがある場合は、Discordの#solanaで質問をしてください。

ヘルプをするときのフローが円滑になるので、エラーレポートには下記の4点を記載してください ✨

1. 質問が関連しているセクション番号とレッスン番号
2. 何をしようとしていたか
3. エラー文をコピー&ペースト
4. エラー画面のスクリーンショット

おめでとうございます!

セクション1は終了です!

ぜひ、あなたのお気に入りのGIF画像が表示されたフロントエンドのスクリーンショットを#solanaに投稿してください 😊

あなたの成功をコミュニティで祝いましょう 🎉

次のレッスンでは、Solanaの開発環境を構築します!