【React】カスタムフックの作成と使い所と実例

2023年1月4日React

Reactのカスタムフックの作成方法と使い方を紹介します。

Reactのカスタムフックとは

useStateなどのReact Hookを内部で使っている関数(フック)のことをカスタムフックといいます。

Reactのカスタムフックの使い所

ReactのHookなどを複数コンポーネントで使いまわしたいときにカスタムフックを使用します。

useStateなどのReactのHookは基本的にはコンポーネントのトップレベルでのみ使用可能です。
ただし、useのつく関数の中では、例外的に使用することができるというReactの決まりごとがあります。
React Hookを関数に切り出すことで、再利用できるようになります。

カスタムフックの関数名

カスタムフックの関数名は、必ずuseなんとかと、頭に「use」をつける必要があります。

カスタムフックの実例

import { createContext, useContext, useState } from "react";

const ModalContext = createContext();

export const ModalProvider = ({ children }) => {
  const [showModal, setShowModal] = useState(false);

  const showModalHandler = () => {
    setShowModal(true);
  };
  const closeModalHandler = () => {
    setShowModal(false);
  };
  return (
    <ModalContext.Provider
      value={{ showModal, showModalHandler, closeModalHandler }}
    >
      {children}
    </ModalContext.Provider>
  );
};

// カスタムフック
export const useModalContext = () => {
  return useContext(ModalContext)
}

createContextとuseContextを使用しています。
これらの説明は、以下を参考にしてみてください。

カスタムフックは、useModalContext部分です。
useContextをリターンしています。その引数にModalContextというcreateContextで作成したコンテキストがあります。
これは、Providerで使いたいコンポーネントをラップして、childrenで使えるようにします。

そして、index.jsなどの使いたいコンポーネントで以下のようにしてラップします。

import * as ReactDOM from "react-dom/client";
import App from "./App";
import { ModalProvider } from "./context/modal-context";
import "./index.css";

const root = ReactDOM.createRoot(document.querySelector("#root"));
root.render(
  <ModalProvider>
    <App />
  </ModalProvider>
);

すると、アプリ全体でvalueに設定した値

value={{ showModal, showModalHandler, closeModalHandler }}

にアクセスすることができます。

あとは、たとえばナビゲーションでモーダルを開きたいという場合、以下のように使います。

import { useModalContext } from "../../context/modal-context";

const Navbar = () => {
  const { showModalHandler } = useModalContext();
  return (
    <nav>
        <button id="theme__icon" onClick={showModalHandler}>
          <IoColorPalette />
        </button>
    </nav>
  );
};

export default Navbar;

そして、モーダルを閉じたいときは、モーダル部分で以下のように使います。

import { createPortal } from "react-dom";
import Card from "./Card";
import { useModalContext } from "../context/modal-context";

const ModalPortal = ({ children }) => {
  const target = document.querySelector("#overlays");
  return createPortal(children, target);
};
const Modal = ({ className, children }) => {
  const { showModal, closeModalHandler } = useModalContext();
  return (
    showModal && (
      <ModalPortal>
        <section id="backdrop" onClick={closeModalHandler}></section>
        <Card className={className}>{children}</Card>
      </ModalPortal>
    )
  );
};

export default Modal;

React

Posted by devsakaso