ヘルプ
サポート

ステート

HTML 要素とコンポーネントを作成する方法、そして JSX を使用して props とイベントハンドラーを両方に渡す方法を学んだので、次は仮想 DOM ツリーを更新する方法を学びましょう。

前の章で述べたように、関数コンポーネントとクラスコンポーネントの両方が、その仮想 DOM ツリーを変更するために使用されるコンポーネントによって格納されるデータである **ステート** を持つことができます。コンポーネントがステートを更新すると、Preact は更新されたステート値を使用してそのコンポーネントを再レンダリングします。関数コンポーネントの場合、これは Preact が関数を再呼び出しすることを意味しますが、クラスコンポーネントの場合はクラスの render() メソッドのみを再呼び出しします。それぞれについて例を見てみましょう。

クラスコンポーネントのステート

クラスコンポーネントには state プロパティがあり、これは render() メソッドが呼び出されるときにコンポーネントが使用できるデータを保持するオブジェクトです。コンポーネントは this.setState() を呼び出して state プロパティを更新し、Preact による再レンダリングを要求できます。

class MyButton extends Component {
  state = { clicked: false }

  handleClick = () => {
    this.setState({ clicked: true })
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.clicked ? 'Clicked' : 'No clicks yet'}
      </button>
    )
  }
}

ボタンをクリックすると、this.setState() が呼び出され、これにより Preact がクラスの render() メソッドを再度呼び出します。this.state.clickedtrue になったので、render() メソッドは「まだクリックされていません」の代わりに「クリックされました」というテキストを含む仮想 DOM ツリーを返し、Preact が DOM 内のボタンのテキストを更新します。

フックを使用した関数コンポーネントのステート

関数コンポーネントもステートを持つことができます!クラスコンポーネントのような this.state プロパティはありませんが、Preact には、関数コンポーネント内でステートを保存および操作するための関数を提供する「フック」と呼ばれる小さなアドオンモジュールが含まれています。

フックは、関数コンポーネント内から呼び出すことができる特別な関数です。それらは、クラスのプロパティやメソッドのように、**レンダリング間で情報を記憶する**ため特別です。たとえば、useState フックは、値とその値を更新するために呼び出すことができる「セッター」関数を含む配列を返します。コンポーネントが複数回呼び出される(再レンダリングされる)と、コンポーネントが行う useState() 呼び出しは、毎回まったく同じ配列を返します。

ℹ️ フックは実際にはどのように機能するのでしょうか?

舞台裏では、setState のようなフック関数は、仮想 DOM ツリー内の各コンポーネントに関連付けられた「スロット」のシーケンスにデータを保存することによって機能します。フック関数を呼び出すと、1つのスロットが消費され、内部の「スロット番号」カウンターが増加して、次の呼び出しで次のスロットが使用されます。Preact は各コンポーネントを呼び出す前にこのカウンターをリセットするため、コンポーネントが複数回レンダリングされると、各フック呼び出しが同じスロットに関連付けられます。

function User() {
  const [name, setName] = useState("Bob")    // slot 0
  const [age, setAge] = useState(42)         // slot 1
  const [online, setOnline] = useState(true) // slot 2
}

これは呼び出しサイト順序と呼ばれ、これがフックが常にコンポーネント内で同じ順序で呼び出される必要があり、条件付きで呼び出したり、ループ内で呼び出したりできない理由です。

useState フックの動作例を見てみましょう

import { useState } from 'preact/hooks'

const MyButton = () => {
  const [clicked, setClicked] = useState(false)

  const handleClick = () => {
    setClicked(true)
  }

  return (
    <button onClick={handleClick}>
      {clicked ? 'Clicked' : 'No clicks yet'}
    </button>
  )
}

ボタンをクリックすると、setClicked(true) が呼び出され、useState() 呼び出しによって作成されたステートフィールドが更新され、これにより Preact がこのコンポーネントを再レンダリングします。コンポーネントが 2 回目にレンダリング(呼び出し)されると、clicked ステートフィールドの値は true になり、返される仮想 DOM は「まだクリックされていません」の代わりに「クリックされました」というテキストになります。これにより、Preact は DOM 内のボタンのテキストを更新します。


試してみましょう!

前の章で作成したコードから始めて、カウンターを作成してみましょう。count 数値をステートに保存し、ボタンがクリックされたときにその値を 1 ずつ増分する必要があります。

前の章では関数コンポーネントを使用したため、フックを使用するのが最も簡単な場合がありますが、どちらのステート保存方法を使用してもかまいません。

読み込み中...