🦏 タイマー処理について
作成日: 2021/12/22
2

setInterval関数を使って処理するが複数の関数とsetEffectを使って処理する

setInterval(一定間隔ごとに実行する関数(コールバック), インターバルの長さ(ms))

順番としては以下。

  • defaultIntervalで秒数を決める
  • 更新可能な変数timerを定め、初期値はundefinedを入れる
  • タイマーが不要になったときにタイマーを削除する必要があるためclearIntervalする関数を作る
  • useEffectで実行されるコンポーネントが削除されるタイミングでタイマーを削除するように下記の様に return (上記で作った関数) する
useEffect(() => {
  setPosition(initialPosition);
  timer = setInterval(() => {
    // do something
  }, defaultInterval);
  return unsubscribe;
}, []);
  • 最初にsetIntervalが実行されたときはまだアクションの初期値も設定されていない状態で関数が生成されてしまうのでtickをuseStateに設定する
  • useEffectの中でゲームの時間を管理するためtimer = setInterval の中でtickをインクリメントしていく処理を書くことで一定間隔でレンダリングがトリガーされるようにする
  • tickの変更が確認できるようになったらuseEffectを追加して第二引数にtickを配列で渡す。これでゲームの中の時間が進むたびに実行関数が呼ばれるようになる

以下モデル

let timer = undefined

const unsubscribe = () => {
  if(!timer) {
    return
  }
  clearInterval(timer)
}

function App() {
  const [fields, setFields] = useState(initialValues)
  const [position, setPosition] = useState(initialPosition)
  const [tick, setTick] = useState(0)

  useEffect(() => {
    setPosition(initialPosition)
    timer = setInterval(() => {
      setTick(tick => tick + 1)
      
    },defaultInterval)
    return unsubscribe
  },[])

  useEffect(() => {
    if(!position){
      return
    }
    goUp()
  },[tick])

  const goUp = () => {
    const {x, y} = position
    const nextY = Math.max(y-1,0)
    fields[y][x] = ''
    fields[nextY][x] = 'snake'
    setPosition({x, y: nextY})
    setFields(fields)
  }