ヘルプ
サポート

チュートリアル

このガイドでは、シンプルな「カウントダウンタイマー」コンポーネントの作成手順を説明します。バーチャルDOMを初めて使用する場合は、Preactの完全なチュートリアルをご覧ください。

ℹ️ このガイドでは、はじめにドキュメントを完了し、ツールを正常に設定済みであることを前提としています。そうでない場合は、Viteから始めましょう。



Hello World

Preactコードベースでは、常に`h()`と`render()`という2つの関数を見かけます。`h()`関数は、JSXをPreactが理解できる構造に変換するために使用されます。ただし、JSXを使用せずに直接使用することもできます。

// With JSX
const App = <h1>Hello World!</h1>;

// ...the same without JSX
const App = h('h1', null, 'Hello World');

これだけでは何も起こりません。Hello WorldアプリをDOMに挿入する必要があります。そのためには、`render()`関数を使用します。

import { render } from 'preact';

const App = <h1>Hello World!</h1>;

// Inject our app into the DOM
render(App, document.getElementById('app'));
REPLで実行

おめでとうございます!最初のPreactアプリを作成しました!

インタラクティブなHello World

テキストのレンダリングは最初のステップですが、アプリをもう少しインタラクティブにしたいです。データの変更時に更新できるようにしたいです。🌟

最終的な目標は、ユーザーが名前を入力して、フォームを送信すると名前が表示されるアプリを作成することです。そのためには、送信した内容を保存できる何かが必要です。ここでコンポーネントが役立ちます。

それでは、既存のAppをコンポーネントに変換しましょう。

import { h, render, Component } from 'preact';

class App extends Component {
  render() {
    return <h1>Hello, world!</h1>;
  }
}

render(<App />, document.getElementById("app"));
REPLで実行

先頭に新しい`Component`インポートが追加され、`App`がクラスに変換されていることに気付くでしょう。これだけでは役に立ちませんが、次にやるべきことの準備段階です。さらに面白くするために、テキスト入力と送信ボタン付きのフォームを追加します。

import { h, render, Component } from 'preact';

class App extends Component {
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <form>
          <input type="text" />
          <button type="submit">Update</button>
        </form>
      </div>
    );
  }
}

render(<App />, document.getElementById("app"));
REPLで実行

さあ、本格的になってきました!実際のアプリらしくなってきました!しかし、まだインタラクティブにする必要があります。「Hello world!」を「Hello, [ユーザー入力]! 」に変更したいので、現在の入力値を知る方法が必要です。

コンポーネントの`state`と呼ばれる特別なプロパティに保存します。これは特別なプロパティで、`setState`メソッドを介して更新されると、Preactは状態を更新するだけでなく、このコンポーネントのレンダリング要求もスケジュールします。要求が処理されると、コンポーネントは更新された状態を使用して再レンダリングされます。

最後に、`value`を設定し、`input`イベントにイベントハンドラをアタッチして、新しい状態を入力にアタッチする必要があります。

import { h, render, Component } from 'preact';

class App extends Component {
  // Initialise our state. For now we only store the input value
  state = { value: '' }

  onInput = ev => {
    // This will schedule a state update. Once updated the component
    // will automatically re-render itself.
    this.setState({ value: ev.currentTarget.value });
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <form>
          <input type="text" value={this.state.value} onInput={this.onInput} />
          <button type="submit">Update</button>
        </form>
      </div>
    );
  }
}

render(<App />, document.getElementById("app"));
REPLで実行

現時点では、ユーザー視点ではアプリはそれほど変わっていませんが、次のステップですべてをまとめます。

入力と同様に、`<form>`の`submit`イベントにハンドラを追加します。違いは、`name`と呼ばれる`state`の別のプロパティに書き込むことです。そして、見出しを入れ替え、そこに`state.name`の値を挿入します。

import { h, render, Component } from 'preact';

class App extends Component {
  // Add `name` to the initial state
  state = { value: '', name: 'world' }

  onInput = ev => {
    this.setState({ value: ev.currentTarget.value });
  }

  // Add a submit handler that updates the `name` with the latest input value
  onSubmit = ev => {
    // Prevent default browser behavior (aka don't submit the form here)
    ev.preventDefault();

    this.setState({ name: this.state.value });
  }

  render() {
    return (
      <div>
        <h1>Hello, {this.state.name}!</h1>
        <form onSubmit={this.onSubmit}>
          <input type="text" value={this.state.value} onInput={this.onInput} />
          <button type="submit">Update</button>
        </form>
      </div>
    );
  }
}

render(<App />, document.getElementById("app"));
REPLで実行

できました!これで、カスタム名を入力して「更新」をクリックすると、新しい名前がヘッダーに表示されます。

クロックコンポーネント

最初のコンポーネントを作成したので、もう少し練習しましょう。今度は時計を作成します。

import { h, render, Component } from 'preact';

class Clock extends Component {
  render() {
    let time = new Date().toLocaleTimeString();
    return <span>{time}</span>;
  }
}

render(<Clock />, document.getElementById("app"));
REPLで実行

簡単ですね!問題は、時間が変わらないことです。時計コンポーネントをレンダリングした時点の時刻で固定されています。

そこで、コンポーネントがDOMに追加されたら1秒タイマーが開始し、削除されたら停止するようにします。`componentDidMount`でタイマーを作成し、その参照を保存し、`componentWillUnmount`でタイマーを停止します。タイマーが刻むごとに、新しい時間値でコンポーネントの`state`オブジェクトを更新します。これにより、コンポーネントが自動的に再レンダリングされます。

import { h, render, Component } from 'preact';

class Clock extends Component {
  state = { time: Date.now() };

  // Called whenever our component is created
  componentDidMount() {
    // update time every second
    this.timer = setInterval(() => {
      this.setState({ time: Date.now() });
    }, 1000);
  }

  // Called just before our component will be destroyed
  componentWillUnmount() {
    // stop when not renderable
    clearInterval(this.timer);
  }

  render() {
    let time = new Date(this.state.time).toLocaleTimeString();
    return <span>{time}</span>;
  }
}

render(<Clock />, document.getElementById("app"));
REPLで実行

またできました!これで、動く時計ができました!