React.js入門(2) ~ステートとフック~

JavaScript

ステートで値を保持する

表示しているコンポーネントをリアルタイムに操作してみる。
画面をクリックしたら表示の値が変わるやつ。

.clickable {
  cursor: pointer;
  font-size: 50px;
}
function App(props) {
  var counter = 0
  const doClick = ()=> {
    counter++
  }

  return (
    <div className="App">
      <h1 className={props.color}>{props.title}</h1>
      <p className={props.color, "clickable"} onClick={doClick}>counter: {counter}.</p>
    </div>
  )
}
クリックしても何も変化しない

関数では値は保持されない

関数コンポーネントが呼び出されたときだけ動き、描画し終わったら消えるものだから。
関数というのは、呼び出されたらその中の処理を実行し、実行し終わったらそれで終わり。
関数の中の変数は実行が終了したら全て消える。

counterもdoClick関数も、実際にユーザーが操作する時にはもう消滅している。

ステートフック

Reactでは、コンポーネントの状態などの値を保持するために「ステート」というものがある。

関数コンポーネントからこのステートを利用するために「ステートフック」と呼ばれる機能がある。
reactというモジュールに用意されている”useState”という関数。

import {useState} from 'react'

このuseState関数は、ステートの値を保管する変数と、値を変更する関数を作成して返す。

const [変数A, 変数B] = useState(初期値)

カウンタを修正する

import {useState} from 'react'

function App(props) {
  const [counter, setCounter] = useState(0)
  const doClick = ()=> {
    setCounter(counter + 1)
  }

  return (
    <div className="App">
      <h1 className={props.color}>{props.title}</h1>
      <p className={props.color, "clickable"} onClick={doClick}>counter: {counter}.</p>
    </div>
  )
}
クリックすると数字が増えるようになった!

副作用フック

副作用フックとは、コンポーネントの更新時に自動的に処理を実行させるためのもの。
useEffectという関数が用意されていて、useState関数同様にimportする必要がある。

import {useState, useEffect} from 'react'
useEffect(関数, [ステート])
  • 第1引数
    • 実行する関数(アロー関数)
  • 第2引数
    • この副作用フックが適用されるステートを配列(つまり複数指定可能)
    • 省略可能
      • 全ての更新で副作用フックが実行されるようになるため、ループ処理になる危険性あり。
      • 特別な理由がない限り、どのステートが更新されたら関数を呼び出すか明示的に指定するのが良さそう。

副作用フックを使ってみる

入力した値が素数かどうか判定させてみる。

import {useState, useEffect} from 'react'

function App(props) {
  const [input, setInput] = useState(1)
  const [message, setMessage] = useState("")

  const doInput = (event)=> {
    setInput(event.target.value)
  }
  useEffect(() => {
    if (input === 1) {
      setMessage("素数ではない")
      return
    }
    for (var i = 2; i < input ; i++) {
      if (input % i === 0) {
        setMessage("素数ではない")
        return
      }
    }
    setMessage("素数です")
  }, [input])

  return (
    <div className="App">
      <h1 className={props.color}>{props.title}</h1>
      <p className={props.color}>{message}</p>
      <input type="number" min="1" onChange={doInput} />
    </div>
  )
}
タイトルとURLをコピーしました