カテゴリデータの管理画面(UI)を実装

解説動画
YouTubeに解説動画を公開しています。 こちらもあわせて、ぜひご覧ください。
カテゴリーページを作成する
1. タブレイアウトにカテゴリータブを追加する
タブレイアウトにカテゴリーページのタブを追加します。
<Tabs.Screen name="categories" options={{ title: "Categories", tabBarIcon: ({ color }) => ( <FontAwesome size={28} name="th-list" color={color} /> ), }} />
2. カテゴリーページを作成する
ベースとなるカテゴリーページを作成します。
(tabs)
ディレクトリにcategories.tsx
を作成します。
import React from "react"; import { Text, View } from "react-native"; export default function Tab() { return ( <View> <Text>categories</Text> </View> ); };
3. カテゴリーページのヘッダーを作成する
ヘッダーを作成します。
Gluestack UIのHeading
コンポーネントとFab
コンポーネントとIcon
コンポーネントをインストールします。
https://gluestack.io/ui/docs/components/heading https://gluestack.io/ui/docs/components/fab https://gluestack.io/ui/docs/components/icon
npx gluestack-ui add heading fab icon
CategoryHeader
コンポーネントを作成します。
(tabs)
ディレクトリにcategory-header.tsx
を作成します。
import React from "react"; import { Text, View } from "react-native"; export default function CategoryHeader() { return ( <View> <Text>CategoryHeader</Text> </View> ); }
カテゴリーページに、空のCategoryHeader
コンポーネントを設置します。
- import { Text, View } from "react-native"; + import { Box } from "@/components/ui/box"; + import { CategoryHeader } from "@/components/category-header"; import React from "react"; export default function Tab() { return ( - <View> - <Text>categories</Text> - </View> + <Box className="flex-1 bg-white"> + <CategoryHeader /> + </Box> ); };
CategoryHeader
コンポーネントを実装します。
_components
ディレクトリにcategories.tsx
を作成します。
import { Box } from "@/components/ui/box"; import { Fab, FabIcon } from "@/components/ui/fab"; import { Heading } from "@/components/ui/heading"; import { AddIcon } from "@/components/ui/icon"; import React from "react"; export default function CategoryHeader() { return ( <Box className="h-16 flex-row items-center justify-between mx-8 my-4"> <Heading size="2xl">カテゴリー</Heading> <Fab size="sm"> <FabIcon as={AddIcon} /> </Fab> </Box> ); }
Fab
コンポーネントをタップできるようにします。
- <Fab size="sm"> + <Fab size="sm" onPress={() => {console.log("add")}}>
4. カテゴリーのカードを作成する
カテゴリーのカードを作成します。
空のCategoryCard
コンポーネントを設置します。
import { Box } from "@/components/ui/box"; import { Fab, FabIcon } from "@/components/ui/fab"; import { Heading } from "@/components/ui/heading"; import { AddIcon } from "@/components/ui/icon"; import React from "react"; export default function Tab() { return ( <Box className="flex-1 bg-white"> <CategoryHeader /> + <Box className="flex-1 bg-gray-100"> + <CategoryCard /> + </Box> </Box> ); };
CategoryCard
コンポーネントを実装します。
Gluestack UIのCard
コンポーネントとButton
コンポーネントをインストールします。
https://gluestack.io/ui/docs/components/card https://gluestack.io/ui/docs/components/button
npx gluestack-ui add card button
import { Button, ButtonIcon } from "@/components/ui/button"; import { Card } from "@/components/ui/card"; import { EditIcon, TrashIcon } from "@/components/ui/icon"; import React from "react"; import { Text } from "react-native"; export default function CategoryCard({ className }: { className?: string }) { return ( <Card className={`bg-white p-4 flex-row items-center rounded-lg shadow-sm ${className}`} > <Text className="text-xl font-bold mr-auto">カテゴリー</Text> <Button variant="link"> <ButtonIcon as={EditIcon} className="m-2 w-6 h-6 text-blue-500" /> </Button> <Button variant="link"> <ButtonIcon as={TrashIcon} className="m-2 w-6 h-6 text-red-500" /> </Button> </Card> ); }
Button
コンポーネントをタップできるようにします。
<Button variant="link" + onPress={() => { + console.log("edit"); + }} > <ButtonIcon as={EditIcon} className="m-2 w-6 h-6 text-blue-500" /> </Button> <Button variant="link" + onPress={() => { + console.log("delete"); + }} > <ButtonIcon as={TrashIcon} className="m-2 w-6 h-6 text-red-500" /> </Button>
体裁を整えます。
import { Box } from "@/components/ui/box"; import React from "react"; import CategoryCard from "../_components/category-card"; import CategoryHeader from "../_components/category-header"; export default function Tab() { return ( <Box className="flex-1 bg-white"> <CategoryHeader /> <Box className="flex-1 bg-gray-100 gap-4 pt-4"> <CategoryCard className="w-11/12 mx-auto" /> </Box> </Box> ); };
5. カテゴリーの登録・編集で使うモーダルを作成する
モーダルを作成します。
Gluestack UIのModal
コンポーネントとInput
コンポーネントをインストールします。
https://gluestack.io/ui/docs/components/modal https://gluestack.io/ui/docs/components/input
npx gluestack-ui add modal input
category-modal.tsx
にCategoryModal
コンポーネントを作成します。
:::details category-modal.tsx
import { Button } from "@/components/ui/button"; import { Heading } from "@/components/ui/heading"; import { Input, InputField } from "@/components/ui/input"; import { Modal, ModalBackdrop, ModalBody, ModalContent, ModalFooter, ModalHeader, } from "@/components/ui/modal"; import React from "react"; import { Text } from "react-native"; export default function CategoryModal({ isOpen, isEdit, onClose, }: { isOpen: boolean; isEdit: boolean; onClose: () => void; }) { return ( <> <Modal isOpen={isOpen} onClose={onClose}> <ModalBackdrop /> <ModalContent> <ModalHeader> <Heading size="lg">カテゴリーの{isEdit ? "編集" : "登録"}</Heading> </ModalHeader> <ModalBody> <Input> <InputField placeholder="カテゴリー名を入力してください" className="bg-gray-100" /> </Input> </ModalBody> <ModalFooter className="w-full"> <Button action="secondary" onPress={onClose}> <Text>キャンセル</Text> </Button> <Button action="positive" onPress={() => console.log("save")}> <Text className="text-white font-bold"> {isEdit ? "更新" : "登録"} </Text> </Button> </ModalFooter> </ModalContent> </Modal> </> ); };
:::
isOpen
プロパティは、モーダルの表示を制御します。
boolean
で、true
であれば開き、false
であれば閉じます。
isEdit
プロパティは、モーダルのタイトルの編集と登録をboolean
で制御します。
onClose
プロパティは、モーダルが閉じられた時に呼び出されるコールバック関数を渡します。
6. カテゴリーの削除で使うアラートダイアログを作成する
アラートダイアログを作成します。
Gluestack UIのAlertDialog
コンポーネントをインストールします。
https://gluestack.io/ui/docs/components/alert-dialog
npx gluestack-ui add alert-dialog
category-alert-dialog.tsx
にCategoryAlertDialog
コンポーネントを作成します。
:::details category-alert-dialog.tsx
import { AlertDialog, AlertDialogBackdrop, AlertDialogContent, AlertDialogFooter, AlertDialogHeader, } from "@/components/ui/alert-dialog"; import { Button } from "@/components/ui/button"; import { Heading } from "@/components/ui/heading"; import React from "react"; import { Text } from "react-native"; export default function CategoryAlertDialog({ isOpen, onClose, }: { isOpen: boolean; onClose: () => void; }) { return ( <> <AlertDialog isOpen={isOpen} onClose={onClose}> <AlertDialogBackdrop /> <AlertDialogContent> <AlertDialogHeader className="mb-4"> <Heading size="lg">カテゴリーを削除しますか?</Heading> </AlertDialogHeader> <AlertDialogFooter> <Button action="secondary" onPress={onClose}> <Text>キャンセル</Text> </Button> <Button action="negative" onPress={() => console.log("delete")}> <Text className="text-white font-bold">削除</Text> </Button> </AlertDialogFooter> </AlertDialogContent> </AlertDialog> </> ); };
:::
7. CategoryHeaderにCategoryModalを設置する
CategoryModal
とuseState
をインポートします。
import CategoryModal from "./category-modal"; import React, { useState } from "react";
useState
を設置します。
const [showModal, setShowModal] = useState(false);
CategoryModal
をFab
の下に設置します。
<CategoryModal isOpen={showModal} isEdit={false} onClose={() => setShowModal(false)} />
Fab
コンポーネントのonPress
でshowModal
をtrue
にします。
<Fab size="sm" onPress={() => { - console.log("add"); + setShowModal(true); }} >
プラスボタンを押すと、モーダルが表示されるようになりました。
モーダルにInput
コンポーネントとButton
コンポーネントを設置します。
Input
コンポーネントとButton
コンポーネントをインポートします。
8. CategoryCardにCategoryModalとCategoryAlertDialogを設置する
CategoryCard
にCategoryModal
とCategoryAlertDialog
を設置します。
import CategoryAlertDialog from "./category-alert-dialog"; import CategoryModal from "./category-modal"; import React, { useState } from "react";
useState
を設置します。
1つ目のuseState
でModal
の表示の切り替えを制御します。
また、2つ目のuseState
でAlertDialog
の表示の切り替えを制御します。
const [showModal, setShowModal] = useState(false); const [showAlertDialog, setShowAlertDialog] = useState(false);
最初のButton
コンポーネントの下に、CategoryModal
を設置します。
<CategoryModal isOpen={showModal} isEdit={true} onClose={() => setShowModal(false)} />
2番目のButton
コンポーネントの下に、CategoryAlertDialog
を設置します。
<CategoryAlertDialog isOpen={showAlertDialog} onClose={() => setShowAlertDialog(false)} />
最初のButton
コンポーネントのonPress
でshowModal
をtrue
にします。
- console.log("edit"); + setShowModal(true);
2番目のButton
コンポーネントのonPress
でshowAlertDialog
をtrue
にします。
- console.log("delete"); + setShowAlertDialog(true);
タグ
関連記事
2025-06-07
2025-06-06
2025-06-04
2025-06-03
2025-06-02