ヘルプ
サポート

コンポーネント

コンポーネントはPreactの基本的な構成要素です。小さな構成要素から複雑なUIを簡単に構築するために不可欠です。また、レンダリングされた出力に状態を付加する役割も担っています。

Preactには2種類のコンポーネントがあり、このガイドで説明します。



関数コンポーネント

関数コンポーネントは、最初の引数として`props`を受け取るプレーンな関数です。JSXで動作させるには、関数名は**必ず**大文字で始める必要があります。

function MyComponent(props) {
  return <div>My name is {props.name}.</div>;
}

// Usage
const App = <MyComponent name="John Doe" />;

// Renders: <div>My name is John Doe.</div>
render(App, document.body);
REPLで実行

以前のバージョンでは`「Stateless Components」`として知られていました。これはフックアドオンではもはや当てはまりません。

クラスコンポーネント

クラスコンポーネントは、状態とライフサイクルメソッドを持つことができます。後者は、コンポーネントがDOMにアタッチされたり、破棄されたりする際に呼び出される特殊なメソッドです。

ここでは、現在時刻を表示する`<Clock>`というシンプルなクラスコンポーネントがあります。

class Clock extends Component {

  constructor() {
    super();
    this.state = { time: Date.now() };
  }

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

  // Lifecycle: 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>;
  }
}
REPLで実行

ライフサイクルメソッド

時計の時刻を毎秒更新するには、`<Clock>`がDOMにマウントされた時点を知る必要があります。 *HTML5カスタムエレメントを使用したことがある場合、これは`attachedCallback`と`detachedCallback`ライフサイクルメソッドに似ています。* Preactは、コンポーネントに対して定義されている場合、以下のライフサイクルメソッドを呼び出します。

ライフサイクルメソッド呼び出されるタイミング
componentWillMount()(非推奨) コンポーネントがDOMにマウントされる前
componentDidMount()コンポーネントがDOMにマウントされた後
componentWillUnmount()DOMから削除される前
componentWillReceiveProps(nextProps, nextContext)新しいpropsが受け入れられる前 *(非推奨)*
getDerivedStateFromProps(nextProps, prevState)`shouldComponentUpdate` の直前。状態を更新するオブジェクトを返すか、更新をスキップするには `null` を返します。注意して使用してください。
shouldComponentUpdate(nextProps, nextState, nextContext)`render()` の前。レンダリングをスキップするには `false` を返します。
componentWillUpdate(nextProps, nextState, nextContext)`render()` の前 *(非推奨)*
getSnapshotBeforeUpdate(prevProps, prevState)`render()` の直前に呼び出されます。戻り値は `componentDidUpdate` に渡されます。
componentDidUpdate(prevProps, prevState, snapshot)`render()` の後

それらが互いにどのように関連しているかの視覚的な概要を次に示します(元々はDan Abramovによるツイートに投稿されました)

Diagram of component lifecycle methods

エラーバウンダリ

エラーバウンダリは、`componentDidCatch()`または静的メソッド`getDerivedStateFromError()`(またはその両方)を実装するコンポーネントです。これらは、レンダリング中に発生するエラーをキャッチできる特別なメソッドであり、通常はより良いエラーメッセージやその他のフォールバックコンテンツを提供し、ログ記録のために情報を保存するために使用されます。エラーバウンダリはすべてのエラーをキャッチできず、イベントハンドラまたは非同期コード(`fetch()`呼び出しなど)でスローされたエラーは別途処理する必要があることに注意することが重要です。

エラーがキャッチされると、これらのメソッドを使用してエラーに対応し、適切なエラーメッセージやその他のフォールバックコンテンツを表示できます。

class ErrorBoundary extends Component {
  constructor() {
    super();
    this.state = { errored: false };
  }

  static getDerivedStateFromError(error) {
    return { errored: true };
  }

  componentDidCatch(error, errorInfo) {
    errorReportingService(error, errorInfo);
  }

  render(props, state) {
    if (state.errored) {
      return <p>Something went badly wrong</p>;
    }
    return props.children;
  }
}
REPLで実行

フラグメント

Fragmentを使用すると、一度に複数の要素を返すことができます。これらは、JSXの制限(すべての「ブロック」には単一のルート要素が必要です)を解決します。リスト、テーブル、またはCSSフレックスボックスと組み合わせて使用されることが多く、そうでなければ中間要素がスタイルに影響を与えます。

import { Fragment, render } from 'preact';

function TodoItems() {
  return (
    <Fragment>
      <li>A</li>
      <li>B</li>
      <li>C</li>
    </Fragment>
  )
}

const App = (
  <ul>
    <TodoItems />
    <li>D</li>
  </ul>
);

render(App, container);
// Renders:
// <ul>
//   <li>A</li>
//   <li>B</li>
//   <li>C</li>
//   <li>D</li>
// </ul>
REPLで実行

ほとんどの最新のトランスパイラでは、Fragmentのより短い構文を使用できます。短い方がはるかに一般的であり、通常は目にするものです。

// This:
const Foo = <Fragment>foo</Fragment>;
// ...is the same as this:
const Bar = <>foo</>;

コンポーネントから配列を返すこともできます。

function Columns() {
  return [
    <td>Hello</td>,
    <td>World</td>
  ];
}

ループ内で作成する場合は、Fragmentにキーを追加することを忘れないでください。

function Glossary(props) {
  return (
    <dl>
      {props.items.map(item => (
        // Without a key, Preact has to guess which elements have
        // changed when re-rendering.
        <Fragment key={item.id}>
          <dt>{item.term}</dt>
          <dd>{item.description}</dd>
        </Fragment>
      ))}
    </dl>
  );
}