15
17

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 3 years have passed since last update.

Jiraっぽいアプリをサクッと作ってみた!

Last updated at Posted at 2021-07-25

はじめに

みなさんこんにちは!
株式会社hokanでフロントエンドエンジニアをしている斉藤と申します!!
初投稿でございます。どうぞよろしくお願いします:clap:
今回はReactでJiraのスクラムボード機能の簡易版を作ったので紹介していこうと思います。
早速ですが成果物はこちらです!
https://jira-clone-4e8c1.web.app

使った技術

  • react-hook-form
  • react-beautiful-dnd
  • Firebase
  • chakra-ui

react-hook-form

react-hook-formはreactのhooksのような感じで使えるフォームライブラリで、react-hook-form側がなんでもやってくれるので、パフォーマンスもよくコードの記述量も減り、onChangeなどを発火させる必要もなくstate管理も楽なパーフェクトライブラリです。

今回はこんな感じで使いました。

import {useForm} from 'react-hook-form'

const {
    register,
    formState: { errors, isSubmitting },
    handleSubmit,
  } = useForm({
    defaultValues: { ...initialValues },
  });

<form onSubmit={onSubmit("create")}>
  <ModalBody>
    <FormControl id="stageItem" isInvalid={!!errors.title}>
      <FormLabel>タイトル</FormLabel>
      <Input
        id="title"
        {...register("title", {
        required: "タイトルは必須です",
       })}
       autoFocus
       />
      <FormErrorMessage>
        {errors.title && errors.title.message}
      </FormErrorMessage>
      <Spacer h={4} />
      <FormLabel>内容</FormLabel>
      <Textarea id="content" {...register("content")} />
      <Spacer h={4} />
      <FormLabel>ステータス</FormLabel>
      <Select {...register("statusId")}>
        {Object.values(DefaultTaskStatusMap).map((status) => (
        <option key={status.id} value={status.id}>
          {status.title}
        </option>
        ))}
      </Select>
    </FormControl>
  </ModalBody>
</form>

 
registerでコンポーネントをフックに登録したら、フォームフィールドの値のバリデーションと値を検知することができるようになり、handleSubmitの引数にhandleSubmit(customOnSubmit)みたいな感じで渡してあげるとcustomOnSubmitの引数にフォームの入力値が入ってきます。
エラーを検知した場合はformStateにエラーメッセージが入ってくるのでエラーハンドリングもピャピャッとできちゃいます。
簡単にフォームをコントロールできちゃいますね。

react-beautiful-dnd

react-beatutiful-dndはドラッグ&ドロップが簡単にできるライブラリです。
<DragDropContext />でドラッグ&ドロップしたいエリアをラップしてあげて、
<Droppable />でラップしたエリアにドロップできるようになり、
<Draggable />でラップしたアイテムがドラッグできるようになります。
こちらのコードのようになるイメージですね!

export const Content: React.FC<Props> = () => {
  const [items, setItems] = useState(_items);
  const onDragEnd = (result: DropResult) => {
    if (!result.destination) return;
    const startIndex = result.source.index;
    const endIndex = result.destination.index;
    const newItems = arrayMove(items, startIndex, endIndex);
    setItems(newItems);
  };
  return (
    <DragDropContext onDragEnd={onDragEnd}>
      <Droppable droppableId={"droppable"} direction={"vertical"}>
        {(provided) => (
          <div ref={provided.innerRef} {...provided.droppableProps}>
            {items.map((item, index) => (
              <Draggable
                key={index}
                index={index}
                draggableId={String(item.id)}
              >
                {(provided) => (
                  <p
                    ref={provided.innerRef}
                    {...provided.draggableProps}
                    {...provided.dragHandleProps}
                  >
                    {item.title}
                  </p>
                )}
              </Draggable>
            ))}
            {provided.placeholder}
          </div>
        )}
      </Droppable>
    </DragDropContext>
  );
};

Firebase

firebaseは今回、firestorehostingauthを利用しました。
詳細な説明は省きますが個人で軽くアプリを作りたい時などにおすすめです!

authは今回はGoogle認証だけ使用しました!
こちらはとても簡単でfirebaseのコンソールでGoogle認証をONにしていただいた後、このコードで簡単にGoogle認証できちゃいます!

const signInWithGoogle = () => {
    const provider = new firebase.auth.GoogleAuthProvider();
    firebase.auth().signInWithPopup(provider);
  };

firestoreはフロントだけでデータのやりとりができサクッとアプリを作りたいときにいいですね!

hosting

  1. firebase cli をインストール
  2. firebase init hosting
  3. firebase deploy --only hosting

の3ステップで完了するのでとても簡単ですね。

chakra-ui

今回一番感動したのはなんといってもこちら、chakra-uiです。
chakra-uiはReact用のコンポーネントライブラリで少ないコードで「いい感じのui」ができちゃう優れものです。

こんな感じでコンポーネントを<ChakraProvider><ChakraProvider/>でラップしてあげるとchakra-uiのテーマが使えるようになり、ダークテーマにも対応しています。

import Routes from "Routes";
import { ChakraProvider } from "@chakra-ui/react";

function App() {
  return (
    <ChakraProvider>
      <Routes />
    </ChakraProvider>
  );
}

export default App;

どれくらい簡単「いい感じのUI」ができるのかサンプルを用意しました!

import {
  Modal as ChakraModal,
  ModalBody,
  ModalOverlay,
  ModalContent,
  ModalHeader,
  ModalCloseButton,
  ModalFooter,
  Button,
  HStack,
  FormControl,
  FormLabel,
  Input,
  Spacer,
  Textarea,
  Select,
  useDisclosure,
} from "@chakra-ui/react";

export const Modal: React.FC = () => {
  const { isOpen, onClose } = useDisclosure();
  return (
    <ChakraModal onClose={onClose} isOpen={isOpen} isCentered>
      <ModalOverlay />
      <ModalContent>
        <ModalHeader>{"タスクを作成"}</ModalHeader>
        <ModalCloseButton />
        <ModalBody>
          <FormControl id="stageItem">
            <FormLabel>タイトル</FormLabel>
            <Input />
            <Spacer h={4} />
            <FormLabel>内容</FormLabel>
            <Textarea />
            <Spacer h={4} />
            <FormLabel>ステータス</FormLabel>
            <Select>
              {Object.values(DefaultTaskStatusMap).map((status) => (
                <option key={status.id} value={status.id}>
                  {status.title}
                </option>
              ))}
            </Select>
          </FormControl>
        </ModalBody>
        <ModalFooter>
          <HStack spacing={3}>
            <Button>{"タスクを作成"}</Button>
            <Button onClick={onClose}>キャンセル</Button>
          </HStack>
        </ModalFooter>
      </ModalContent>
    </ChakraModal>
  );
};

こちらのサンプルでこんな感じのモーダルができちゃいます!
スクリーンショット 2021-07-26 2.39.33.png

このモーダル、chakra-uiのコンポーネントだけで作っているのですがほとんどカスタムしてません。
const { isOpen, onClose, onOpen } = useDisclosure()でモーダルやダイアログ、ドロワーなどの状態を管理できたりします。
自分で作るとちょっと面倒なUIも作ってくれており、デフォルトでこんないい感じのUI作れちゃうのはとても気持ちがいいですね。
他にもaria属性の定義や、キーボードナビゲーションへの配慮もあるのでアクセシビリティも問題ありません。
chakra-uiは今後も積極的に使っていきたいと強く思いました!

所感

今回はやってみた系の記事でベテランエンジニアの方には特に学ぶこともなかったかと思いますが、駆け出しエンジニアの皆様やフロントやったことないエンジニアの方には役に立っていただけたら嬉しいです!
初めての記事でとても大変でしたがこれからも頑張って描いていこうと思いました。

15
17
2

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
15
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?