カスタムフックも雰囲気で知っていたのでアウトプットします。(何番煎じだよ感がありますが......)
カスタムフックは複数のコンポーネントの中に存在する共通の処理を取り出して作成した関数です。汎用的なカスタムフックを作成することができれば1つのアプリケーション内で再利用するだけではなく複数のアプリケーションでも再利用することが可能になります。
カスタムフックを作る際のルール
メソッド名はuseを接頭辞にする
カスタムフック内ではデフォルトのフックを利用する
戻り値のパターンはデフォルトのフックに従う
以下は公式のコピペです。
import React, { useState, useEffect } from 'react';
function FriendStatus(props) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
import React, { useState, useEffect } from 'react';
function FriendListItem(props) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
return (
<li style={{ color: isOnline ? 'green' : 'black' }}>
{props.friend.name}
</li>
);
}
この2つのコードには重複している部分があります。
それが以下で、ここではフレンドステータスがオンラインかオフラインかを判別しています。
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
上記コードはカスタムフックを使用することでスッキリさせることができます。
以下のコードはカスタムフックとしてファイル名はお作法通りuse
から始まるものになっています。
このフックは返り値として対象のユーザーがオンラインかオフラインかだけを教えてくれるフックです。
返り値はuseStateで管理しているisOnlineを返しています。
import { useState, useEffect } from 'react';
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
};
});
return isOnline;
}
カスタムフックを使う側のコードを見てみましょう
function FriendStatus(props) {
const isOnline = useFriendStatus(props.friend.id);
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
function FriendListItem(props) {
const isOnline = useFriendStatus(props.friend.id);
return (
<li style={{ color: isOnline ? 'green' : 'black' }}>
{props.friend.name}
</li>
);
}
めちゃめちゃスッキリしたのと、FriendStatusコンポーネントとFriendListItemコンポーネントにロジックを書くことがなくなり、この二つのコンポーネントはあくまでビュー部分を担当とする責務を持たせることができました。
追記: ゴミみたいなカスタムフックを作成した
import { useState, useEffect, useCallback } from "react";
type Mood = "happy" | "sad" | "pien";
type Emotion = "😀" | "😭" | "🥺";
export default function useEmotion(mood: Mood) {
const [emotion, setEmotion] = useState<Emotion>();
const getEmotion = useCallback((mood: Mood) => {
switch (mood) {
case "happy":
return "😀";
case "sad":
return "😭";
case "pien":
return "🥺";
default:
return;
}
}, []);
useEffect(() => {
setEmotion(getEmotion(mood));
}, [mood]);
return emotion;
}
import useEmotion from "./hooks/useEmotion";
export default function App() {
const emotion = useEmotion("pien");
return <div className="App">{emotion}</div>;
}
参考