👕
画面サイズで制御するカスタムフック作ってみた
はじめに
ウィンドウのサイズで、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
}
追加したこととしては、useEffect
でresizeEvent
の関数を呼び出しています。
またカスタムフックの returnとしてstate(open)とsetState(setOpen)を返しています。
命名が、もうちょっと広義でこのカスタムフックに合わせた名前にしたいところ。
useWindowResizeフックを使いたい箇所では、使う用途に合わせて受け取る名前を変えても良さそう
const ItemBox = () => {
const [isSp] = useWindowResize()
~~ 処理 ~~
}
上記の例のコンポーネントでは、スマートフォンのサイズかを判別できるようにisSpとして受け取っています。
おわり
ウィンドウのサイズで、stateの状態の変更できるカスタムフックカスタムでした。
Discussion