Astro FrameworkにReactを導入する流れ – フレームワークAstro.jsで静的サイト制作

※このページはプロモーションを含みます

はじめに

フレームワークAstro.jsではReactを導入して部分的にインタラクティブなページを構築することができます。

公式 チュートリアルは体系的に学べるのが良いのですがサッと見て思い出したいときのために記事に残しておこうと思います。

まっさらな Astro Framework のプロジェクトを作ろう

[前提条件]

  • wsl2内で作業します。
  • ディレクトリ名はreactとしています。

reactディレクトに移動して下記コマンドを入力します。

 cd ~/react
 npm create astro@latest
 # コマンドで何個か質問があってそれを答え終わるとプロジェクトが生成されます
~~~ 省略 ~~~

 # インテグレーションにReactを登録する 
 npx astro add react 

npx astro add reactというコマンドを打つだけでastro.config.mjsに下記オプションが追加されます。

import react from '@astrojs/react';

// https://astro.build/config
export default defineConfig({
  integrations: [react()]
});

ここまでで出来た内容を確認してみます。

npm run dev 

http://localhost:4321にアクセスすると下記のようなページが表示されました。

localhost:4321の表示

これでReactコンポーネントを追加する準備ができました。

Reactでコンテンツを表示する

Components フォルダを作成してReactのコンポーネントを呼び出すようにします。

mkdir -p src/components
cd src/components
touch sample.jsx

sample.jsxに適当なコンポーネントを用意します。

 const Sample = () => {
    return (
        <div>
            <p>はじめてのコンポーネントです</p>
        </div>
    );
};

export default Sample;

呼び出すファイルを次のようにしました。

---
import Sample from '../components/sample.jsx';
---

<html lang="ja">
	<head>
		<meta charset="utf-8" />
		<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
		<meta name="viewport" content="width=device-width" />
		<meta name="generator" content={Astro.generator} />
		<title>Astro</title>
	</head>
	<body>
		<h1>Astro</h1>
		<Sample />
	</body>
</html>

補足

---で囲まれた箇所を「フロントマター」と呼びます。

実際の表示がこちら↓

localhost:4321の画面

「はじめてのコンポーネントです」部分がReactで生成されています。ただし静的な表示なのでこの段階ではReactである意味はありませんね。

ここでbuildしてみるとどうなるでしょう?

npm run build

「dist」フォルダが生成されデプロイ用ファイル達ができました。

buildしたものをプレビューできるコマンドが用意されているのでプレビューします。

npm run preview     

問題なくプレビューできました。

コンポーネントにclickイベントを追加する

コンポーネントにイベント処理を追加します。

const Sample = () => {

    const handleClick = () => {
        alert('clicked !');
    }

    return (
        <div>
            <h1>はじめてのコンポーネントです</h1>
            <button onClick={handleClick}>ボタン押下でアラート表示</button>
        </div>
    );
};

export default Sample;

これでクリックするとアラートが表示される処理が追加できました。

プレビュー画面でボタンを押してみます。

・・・ボタンを押してもうんともすんとも動きません。

Astro Frameworkではさらにもう一処理必要になります。

コンポーネントを呼び出す時にclient:○○をつけなければjavascriptは動かない

Reactコンポーネントを呼び出す際にclient:loadを追加するとアラートが表示されるようになります。

このclientのところは公式には「テンプレートディレクティブ」と呼びます。

これを指定しないかぎりReactで書いたコンポーネントでも静的なHTMLとして扱われます。つまりJavascriptを含まないHTMLとしてページに表示されます。

※このディレクティブを使用できるのは.astroファイル内のみで.jsxなどのファイルで使用しても何もおこりません。

client:*のディレクティブは何種類かあります。

この記述によってコンポーネントの処理タイミングを細かく指定することができます。

  • client:load ページの読み込みと同時
  • client:idle ブラウザが待機状態になったとき
  • client:visible コンポーネントが画面内に表示されたとき
  • client:media 指定したCSSメディアクエリの条件が満たされたとき
  • client:only コンポーネントが使用しているフレームワークを正確に指定したいとき

Reactコンポーネントを少し複雑なものにする

上記のコンポーネントはあまりに単純すぎるので計算機(電卓)をReactコンポーネントで表示してみます。

components/Calcurator.jsxファイルとスタイルを設定するcssファイルを作成します。

cd src/components
touch Calcurator.jsx Calcurator.css    

Calcurator.jsxに電卓処理を書きます

// Calcurator.jsx
import React, { useState } from 'react';
import './Calcurator.css';

const Calcurator = () => {
  const [input, setInput] = useState(''); // 現在の入力内容
  const [result, setResult] = useState(''); // 計算結果

  const handleButtonClick = (value) => {
    if (value === 'C') {
      setInput('');
      setResult('');
    } else if (value === '=') {
      try {
        setResult(eval(input)); // evalで式を評価して計算結果を表示
      } catch {
        setResult('エラー');
      }
    } else {
      setInput(input + value);
    }
  };

  const buttons = [
    '7', '8', '9', '/',
    '4', '5', '6', '*',
    '1', '2', '3', '-',
    '0', '.', '=', '+',
    'C'
  ];

  return (
    <div className="calculator">
      <div className="display">
        <div className="input">{input}</div>
        <div className="result">{result}</div>
      </div>
      <div className="buttons">
        {buttons.map((button) => (
          <button
            key={button}
            onClick={() => handleButtonClick(button)}
          >
            {button}
          </button>
        ))}
      </div>
    </div>
  );
};

export default Calcurator;

Calcurator.cssで見た目を調整します

/* Calcurator.css */
.calculator {
    width: 200px;
    margin: 0 auto;
    text-align: center;
    background-color: #f2f2f2;
    border-radius: 8px;
    padding: 20px;
    box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);

    .display {
        font-size: 24px;
        margin-bottom: 10px;
    }

    .buttons {
        display: grid;
        grid-template-columns: repeat(4, 1fr);
        gap: 5px;
    }

    button {
        font-size: 18px;
        padding: 10px;
        cursor: pointer;
    }
}

astroファイルでコンポーネントを呼びだします

---
import Sample from '../components/sample.jsx';
import Calcurator from '../components/Calcurator.jsx';
---

<html lang="ja">
	<head>
		<meta charset="utf-8" />
		<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
		<meta name="viewport" content="width=device-width" />
		<meta name="generator" content={Astro.generator} />
		<title>Astro</title>
	</head>
	<body>
		<h1>Astro</h1>
		<Sample client:load />
		<Calcurator client:load />
	</body>
</html>

結果は以下の表示になりました。電卓も無事動きました。

最後に

AstroフレームワークにReactを導入する流れをまとめておきます。

  1. Astroプロジェクトを生成(npm コマンド)
  2. AstroインテグレーションにReactを追加設定(npm コマンド)
  3. コンポーネント用ディレクトリの作成(コマンドもしくはエディタなどで)
  4. Reactコンポーネントを作成(各エディタで)
  5. 呼び出したい場所(Astroファイル)にReactコンポーネントをclientディレクティブ付で読み込む(各エディタで)

以上で簡単ですがAstroフレームワークにReactコンポーネントを導入することができます。