2
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?

Chakra v2からChakra v3へ極力手を抜きながら移行する方法

Last updated at Posted at 2024-10-23

結論

Wrapperをつくる

まえがき

ついにChakra v3が来ましたね。framer-motionの依存がなくなり、軽量かつ高速になったようです。しかし、当然ながら破壊的変更が多く、移行のコストが大きいと感じました。そこで、今回は移行を進めていく際の方針を共有します。

V2Modal

TestModal.tsx
import { useDisclosure } from "@chakra-ui/react";
import {
  Button,
  Modal,
  ModalBody,
  ModalCloseButton,
  ModalContent,
  ModalFooter,
  ModalHeader,
  ModalOverlay,
  useDisclosure,
} from "@chakra-ui/react";
export const TestModal = () => {
  const { isOpen, onOpen, onClose } = useDisclosure();
  return (
    <>
      <Button onClick={onOpen} size={"sm"} closeOnEsc={true}>
        Open
      </Button>

      <Modal isOpen={isOpen} onClose={onClose}>
        <ModalOverlay />
        <ModalContent>
          <ModalHeader>header</ModalHeader>
          <ModalCloseButton />
          <ModalBody>body</ModalBody>
          <ModalFooter>
            <Button colorScheme="blue" mr={3} onClick={onClose}>
              Close
            </Button>
            <Button variant="ghost">Secondary Action</Button>
          </ModalFooter>
        </ModalContent>
      </Modal>
    </>
  );
};

超基本的なモーダルですね。V3ではModalがなくなりDialogになっています。いろいろ変わってしまっており、このままでは動きません。

Wrapperを用意する

Modal.tsx
import {
  DialogBackdrop,
  DialogBody,
  DialogCloseTrigger,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogRoot,
} from "@/components/ui/dialog";

type ModalProps = {
  children: React.ReactNode;
  isOpen: boolean;
  onClose: () => void;
  closeOnEsc?: boolean;
};
export const Modal = ({
  children,
  isOpen,
  onClose,
  closeOnEsc,
}: ModalProps) => {
  const onOpenClose = () => {
    if (isOpen) {
      onClose();
    }
  };
  return (
    <DialogRoot
      open={isOpen}
      onOpenChange={onOpenClose}
      closeOnEscape={closeOnEsc}
    >
      {children}
    </DialogRoot>
  );
};

export const ModalBody = DialogBody;
export const ModalCloseButton = DialogCloseTrigger;
export const ModalOverlay = DialogBackdrop;
export const ModalHeader = DialogHeader;
export const ModalFooter = DialogFooter;
export const ModalContent = DialogContent;

こういうwrapperを用意すれば、呼び出し元はimport先を変更するだけで大丈夫です。

WrapperからModalを呼び出す

TestModal.tsx
import { Button, useDisclosure } from "@chakra-ui/react";
import {
  Modal,
  ModalBody,
  ModalCloseButton,
  ModalContent,
  ModalFooter,
  ModalHeader,
  ModalOverlay,
} from "../components/v2/Modal";
export const TestModal = () => {
  const { open: isOpen, onOpen, onClose } = useDisclosure();
  return (
    <>
      <Button onClick={onOpen} size={"sm"}>
        Open
      </Button>

      <Modal isOpen={isOpen} onClose={onClose} closeOnEsc={true}>
        <ModalOverlay />
        <ModalContent>
          <ModalHeader>header</ModalHeader>
          <ModalCloseButton />
          <ModalBody>body</ModalBody>
          <ModalFooter>
            <Button colorScheme="blue" mr={3} onClick={onClose}>
              Close
            </Button>
            <Button variant="ghost">Secondary Action</Button>
          </ModalFooter>
        </ModalContent>
      </Modal>
    </>
  );
};

import先が変わっただけで、他の部分は何も変えなくて良いですね。useDisclosureがisOpen -> openに変更されていたり、colorSchemeがcolorPaletteになっていたり、isDisabledがdisabledになっていたり、closeOnEscがcloseOnEscapeになっていたりと細かい変更点があります。こういう部分も含めたWrapperを書いてあげると良いでしょう。

というかV2とV3を混在させたい場合

あんまりおすすめしませんが(バンドルサイズもやばいことになるし)、やるなら使うコンポーネントだけをV2からインポートしてエクスポートするだけのWrapperライブラリを作成します。V2のコンポーネントを使うときだけは、そのWrapperライブラリからインポートするようにすればV2とV3が共存できます。やらんほうが良いと思うけど一応。

新しいコンポーネントを書くときにV3を利用しつつ、いままで書いてきたコンポーネントたちはWrapperでとりあえず動く状態にする、というのが一番手軽だと思います。でもcolorPaletteが変わっていたり、inputのデザインが変わっていたりと非常に破壊的な変更があるため、全然違うデザインになってしまうなぁ、という問題があります。いまのプロジェクトはV2系でいって、次のプロジェクトからV3にするとかの選択肢もあるでしょうね。そのほうが楽かな……。

chakra v3にしてみたら700個くらいtypeエラーが出て諦めそうになりましたが、Wrapperを書く方針にしてからは2時間くらいでなんとかなりました。デザイン変わりすぎたので、そのブランチはお蔵入りになりましたが……。

2
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
2
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?