👕

画面サイズで制御するカスタムフック作ってみた

2021/12/08に公開

はじめに

ウィンドウのサイズで、stateの状態の変更できる処理をカスタムフックで他のファイルでも使える状態にしたかったので実装
学習用メモになります。

環境

"typescript": "^4.1.3",
"react": "^17.0.1",

実装結果

useWindowResize.ts

import React, { useCallback, useEffect, useState } from 'react'

export const useWindowResize = () => {
  const [open, setOpen] = useState(false)

  useEffect(() => {
    if (window.innerWidth >= 768) {
      setOpen(true)
    }
    resizeEvent()
    return () => window.removeEventListener('resize', resizeEvent);
  }, [])

  // 画面をリサイズした時にstate調整
  const resizeEvent = useCallback(() => {
    window.addEventListener('resize', () => {
      if (window.innerWidth < 768) {
        setOpen(false)
      } else {
        setOpen(true)
      }
    })
  },[open])

  return [ open, setOpen ] as const
}

内容を見ていく

1.ResizeEvent用の関数用意

ウィンドウの大きさが変更される時に合わせて変更できるように関数を用意しました

~~ 省略 ~~
const [open, setOpen] = useState(false)

const resizeEvent = useCallback(() => {
  window.addEventListener('resize', () => {
    if (window.innerWidth < 768) {
      setOpen(false)
    } else {
      setOpen(true)
    }
  })
},[open])
~~ 省略 ~~

2.最初の描画時にサイズを確認し、状態を変更

最初のwindowのinnerWidthを確認し、状態変更をします。

const [open, setOpen] = useState(false)

useEffect(() => {
  if (window.innerWidth >= 768) {
    setOpen(true)
  }
}, [])

3. 1と2を組み合わせる

import React, { useCallback, useEffect, useState } from 'react'

export const useWindowResize = () => {
  const [open, setOpen] = useState(false)

  useEffect(() => {
    if (window.innerWidth >= 768) {
      setOpen(true)
    }
+   resizeEvent()
+   return () => window.removeEventListener('resize', resizeEvent);
  }, [])

  // 画面をリサイズした時にstate調整
  const resizeEvent = useCallback(() => {
    window.addEventListener('resize', () => {
      if (window.innerWidth < 768) {
        setOpen(false)
      } else {
        setOpen(true)
      }
    })
  },[open])

+  return [ open, setOpen ] as const
}

追加したこととしては、useEffectresizeEventの関数を呼び出しています。
またカスタムフックの returnとしてstate(open)とsetState(setOpen)を返しています。
命名が、もうちょっと広義でこのカスタムフックに合わせた名前にしたいところ。

useWindowResizeフックを使いたい箇所では、使う用途に合わせて受け取る名前を変えても良さそう

const ItemBox = () => {
  const [isSp] = useWindowResize()
  ~~ 処理 ~~
}

上記の例のコンポーネントでは、スマートフォンのサイズかを判別できるようにisSpとして受け取っています。

おわり

ウィンドウのサイズで、stateの状態の変更できるカスタムフックカスタムでした。

参考

useEffect完全ガイド
Window: resize イベント

Discussion