🐈
React用のデバイス判別フック作ったので、みんなに共有
経緯
もともと、react-device-detectというライブラリを利用させてもらってたんだけど、思った動作をしないので(使い方が悪かったのかも?)、自分で作りました。
前提環境
- nodejs・npmインストール済み
- React
インストール
全体コード
'use client';
import { useCallback, useEffect, useState } from 'react';
interface ReturnDeviceType {
error: unknown;
isMobile: boolean;
isAndroid: boolean;
isIos: boolean;
isTablet: boolean;
isDesktop: boolean;
isUnknown?: boolean;
}
const DEVICE_UA_TYPE = {
desktop: /Windows NT|Macintosh|Linux|CrOS/i,
tablet: {
primary: /iPad|Android(?!.*Mobile)|Windows.*Touch/i,
secondary: /Macintosh/i,
},
mobile: {
all: /iPhone.*Mobile|Android.*Mobile|Windows Phone|BlackBerry/i,
android: /Android.*Mobile/i,
iphone: /iPhone.*Mobile/i,
},
};
const useDeviceType = (deviceUnknowNullable = false) => {
const [loaded, setLoaded] = useState<boolean>(false);
const [deviceInfo, setDeviceInfo] = useState<ReturnDeviceType>({
// 状態値
error: null,
// モバイル
isMobile: false,
isAndroid: false,
isIos: false,
// タブレット
isTablet: false,
// PC
isDesktop: false,
isUnknown: false,
});
const getDeviceType = useCallback(() => {
const ua = navigator.userAgent;
const width = window.innerWidth;
const hasTouch = 'ontouchstart' in window;
const testRegex = (type: RegExp) => type.test(ua);
const mobileRgx = DEVICE_UA_TYPE.mobile;
const newDeviceType: Partial<ReturnDeviceType> = {
isMobile: false,
isAndroid: false,
isIos: false,
isTablet: false,
isDesktop: false,
isUnknown: false,
};
try {
// PC判定
if (testRegex(DEVICE_UA_TYPE.desktop) && width >= 960) {
newDeviceType.isDesktop = true;
}
// タブレット
else if (
testRegex(DEVICE_UA_TYPE.tablet.primary) ||
(testRegex(DEVICE_UA_TYPE.tablet.secondary) && width <= 1024 && hasTouch)
) {
newDeviceType.isTablet = true;
}
// モバイル
else if (testRegex(mobileRgx.all)) {
newDeviceType.isMobile = true;
// android
if (testRegex(mobileRgx.android)) {
newDeviceType.isAndroid = true;
} else if (testRegex(mobileRgx.iphone)) {
newDeviceType.isIos = true;
}
} else newDeviceType.isUnknown = true;
if (!deviceUnknowNullable) {
delete newDeviceType.isUnknown;
}
setDeviceInfo(newDeviceType as ReturnDeviceType);
} catch (err) {
console.error(err);
setDeviceInfo((prevState) => ({
...prevState,
error: err,
}));
}
}, [deviceUnknowNullable]);
useEffect(() => {
getDeviceType();
setLoaded(true);
}, [getDeviceType]);
return { loaded, ...deviceInfo };
};
export default useDeviceType;
- 上のコードをコピー
- 好きな場所に、
useDeviceType.tsというファイルを作成
※ファイル名は何でもいいですが、変更したらexport defaultの変数名?も変更してください - あとは、足りないライブラリとかをインストールしたら使用できます。
使い方
通常のカスタムフックと使い方は一緒です。
const { loaded, error, isTablet, isDesktop } = useDeviceType();
isUnknown
このカスタムフックには、isUnknownというプロパティがあります。
端末がなにか不明だった場合のため、エラーではなくisUnknownがbooleanで返ります。
基本的には、このプロパティはundefinedになっていますが、下のようにTrueに変更すればbooleanが返るようになります。
const { isUnknown, ... } = useDeviceType(true);
テストコード
export default function TestNode() {
const dt = useDeviceType();
useEffect(() => {
console.log(dt);
}, []);
return(<></>)
}
上のコードを試してみて、下のようなログが出たら正常に動いています。
※環境によって変わる可能性があります。

備考
不明点があれば、お気軽にご連絡ください
Discussion