0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

React: カスタムフック [アウトプット全くしてこなかったのでアウトプットする014]

Last updated at Posted at 2022-03-13

カスタムフックも雰囲気で知っていたのでアウトプットします。(何番煎じだよ感がありますが......)

カスタムフックは複数のコンポーネントの中に存在する共通の処理を取り出して作成した関数です。汎用的なカスタムフックを作成することができれば1つのアプリケーション内で再利用するだけではなく複数のアプリケーションでも再利用することが可能になります。

カスタムフックを作る際のルール
メソッド名はuseを接頭辞にする
カスタムフック内ではデフォルトのフックを利用する
戻り値のパターンはデフォルトのフックに従う

以下は公式のコピペです。

FriendStatus.js
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';
}
FriendListItem.jsx
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を返しています。

useFriendStatus.jsx
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;
}

カスタムフックを使う側のコードを見てみましょう

FriendStatus.jsx
function FriendStatus(props) {
  const isOnline = useFriendStatus(props.friend.id);

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}
FriendListItem.jsx
function FriendListItem(props) {
  const isOnline = useFriendStatus(props.friend.id);

  return (
    <li style={{ color: isOnline ? 'green' : 'black' }}>
      {props.friend.name}
    </li>
  );
}

めちゃめちゃスッキリしたのと、FriendStatusコンポーネントとFriendListItemコンポーネントにロジックを書くことがなくなり、この二つのコンポーネントはあくまでビュー部分を担当とする責務を持たせることができました。

追記: ゴミみたいなカスタムフックを作成した

useEmotion.tsx
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;
}
App.tsx
import useEmotion from "./hooks/useEmotion";

export default function App() {
  const emotion = useEmotion("pien");
  return <div className="App">{emotion}</div>;
}

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?