ヘルプ
ご支援ください

Refs

最初の章で学んだように、DOM は命令型の API を提供しており、要素に対して関数を呼び出すことで変更を加えることができます。Preact コンポーネントから命令型の DOM API にアクセスする必要がある例の 1 つとして、入力要素に自動的にフォーカスを移動することが挙げられます。

autoFocus プロパティ (または autofocus 属性) を使用すると、最初レンダリングされたときに入力にフォーカスを当てることができます。ただし、特定のタイミングや特定のイベントに応答して、入力にフォーカスを移動したい場合があります。

DOM 要素と直接やり取りする必要があるこれらのケースでは、「refs」と呼ばれる機能を使用できます。ref は、任意の値を指す current プロパティを持つプレーンな JavaScript オブジェクトです。JavaScript オブジェクトは参照渡しされるため、ref オブジェクトにアクセスできるすべての関数は、current プロパティを使用して値を取得または設定できます。Preact は ref オブジェクトの変更を追跡しないため、レンダリング中に情報を保存するために使用でき、ref オブジェクトにアクセスできるすべての関数が後でアクセスできます。

何もレンダリングせずに ref 機能の直接的な使用方法を見てみましょう。

import { createRef } from 'preact'

// create a ref:
const ref = createRef('initial value')
// { current: 'initial value' }

// read a ref's current value:
ref.current === 'initial value'

// update a ref's current value:
ref.current = 'new value'

// pass refs around:
console.log(ref) // { current: 'new value' }

Preact で refs が役立つのは、レンダリング中に ref オブジェクトを仮想 DOM 要素に渡すことができ、Preact が ref の値 (current プロパティ) を対応する HTML 要素に設定することです。設定したら、ref の現在の値を使用して HTML 要素にアクセスして変更できます。

import { createRef } from 'preact';

// create a ref:
const input = createRef()

// pass the ref as a prop on a Virtual DOM element:
render(<input ref={input} />, document.body)

// access the associated DOM element:
input.current // an HTML <input> element
input.current.focus() // focus the input!

グローバルに createRef() を使用することはお勧めしません。複数のレンダリングによって ref の現在の値が上書きされるためです。代わりに、ref をクラス プロパティとして保存するのが最適です。

import { createRef, Component } from 'preact';

export default class App extends Component {
  input = createRef()

  // this function runs after <App> is rendered
  componentDidMount() {
    // access the associated DOM element:
    this.input.current.focus();
  }

  render() {
    return <input ref={this.input} />
  }
}

関数コンポーネントの場合、useRef() フックは ref を作成し、後続のレンダリングで同じ ref にアクセスするための便利な方法を提供します。次の例では、コンポーネントがレンダリングされた後にコールバックを呼び出すために useEffect() フックを使用する方法も示しています。その際、ref の現在の値は HTML 入力要素に設定されます。

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

export default function App() {
  // create or retrieve our ref:  (hook slot 0)
  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} />
}

ref は DOM 要素の格納だけに限らないことを覚えておいてください。追加のレンダリングを引き起こすステートを設定せずに、コンポーネントのレンダリング間で情報を格納するために使用できます。それらの使用例については、後の章で説明します。

試してみよう!

では、これを実践するために、クリックすると ref を使用して入力フィールドにアクセスし、フォーカスを当てるボタンを作成してみましょう。

ロード中...