ヘルプ
私たちをサポート

副作用

副作用とは、仮想 DOM ツリー内で変更が発生したときに実行されるコードの一部です。これらは、propsを受け取って新しい仮想 DOM ツリーを返すという標準的なアプローチに従わず、多くの場合、ツリーから離れて状態を変化させたり、DOM API の呼び出しなどの命令型コードを呼び出したりします。副作用は、データフェッチをトリガーする方法としてもよく使用されます。

エフェクト: 関数コンポーネントにおける副作用

以前の章で、refとuseRef()フックについて学習した際に、副作用の動作例をすでに見てきました。 refにDOM要素を指すcurrentプロパティが設定されたら、その要素と対話するコードを「トリガー」する方法が必要でした。

レンダリング後にコードをトリガーするために、関数コンポーネントから副作用を作成する最も一般的な方法であるuseEffect()フックを使用しました。

import { useRef, useEffect } from 'preact/hooks';

export default function App() {
  const input = useRef()

  // the callback here will run after <App> is rendered:
  useEffect(() => {
    // access the associated DOM element:
    input.current.focus()
  }, [])

  return <input ref={input} />
}

useEffect()への2番目の引数として渡される空の配列に注目してください。エフェクトコールバックは、その「依存関係」配列の値がレンダリング間で変更された場合に実行されます。たとえば、コンポーネントが最初にレンダリングされるとき、比較する以前の「依存関係」配列の値がないため、すべてのエフェクトコールバックが実行されます。

コンポーネントが最初にレンダリングされたときだけでなく、条件に基づいてエフェクトコールバックをトリガーするために、「依存関係」配列に値を追加できます。これは通常、データ変更に応答してコードを実行したり、コンポーネントがページから削除された(「アンマウントされた」)ときに実行するために使用されます。

例を見てみましょう。

import { useEffect, useState } from 'preact/hooks';

export default function App() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log('<App> was just rendered for the first time')
  }, [])

  useEffect(() => {
    console.log('count value was changed to: ', count)
  }, [count])
  //  ^ run this any time `count` changes, and on the first render

  return <button onClick={() => setCount(count+1)}>{count}</button>
}

ライフサイクルメソッド: クラスコンポーネントの副作用

クラスコンポーネントは、Preactが提供するライフサイクルメソッドを実装することで、副作用を定義することもできます。最も一般的に使用されるライフサイクルメソッドをいくつか紹介します。

ライフサイクルメソッド実行されるタイミング
componentWillMountコンポーネントが最初にレンダリングされる直前
componentDidMountコンポーネントが最初にレンダリングされた後
componentWillReceivePropsコンポーネントが再レンダリングされる前
componentDidUpdateコンポーネントが再レンダリングされた後

クラスコンポーネントでの副作用の最も一般的な使用例の1つは、コンポーネントが最初にレンダリングされたときにデータをフェッチし、そのデータを状態に格納することです。次の例は、最初にレンダリングされた後にJSON APIからユーザー情報をリクエストし、その情報を表示するコンポーネントを示しています。

import { Component } from 'preact';

export default class App extends Component {
  // this gets called after the component is first rendered:
  componentDidMount() {
    // get JSON user info, store in `state.user`:
    fetch('/api/user')
      .then(response => response.json())
      .then(user => {
        this.setState({ user })
      })
  }

  render(props, state) {
    const { user } = state;

    // if we haven't received data yet, show a loading indicator:
    if (!user) return <div>Loading...</div>

    // we have data! show the username we got back from the API:
    return (
      <div>
        <h2>Hello, {user.username}!</h2>
      </div>
    )
  }
}

試してみよう!

この演習は簡単にしておきましょう。<App>が最初にレンダリングされたときだけでなく、countが変更されるたびにログに記録するように、右側のコードサンプルを変更してください。

読み込み中...