React File Manager를 만들어 봅시다. 20장: Create Directory 버튼 만들기
47106 단어 typescriptmongezjavascriptreact
create directory
버튼과 작업을 만들어 보겠습니다.UI
UI는 매우 간단합니다. 더하기 아이콘이 있는 버튼이 있고 사용자가 버튼을 클릭하면 새 디렉토리를 생성하는 양식이 있는 모달이 표시됩니다.
// components/Toolbar/Buttons/CreateDirectoryButton.tsx
export default function CreateDirectoryButton() {
return <div>CreateDirectoryButton</div>;
}
이제 툴바에서 가져오겠습니다.
// components/Toolbar/Toolbar.tsx
import { Grid } from "@mantine/core";
import CreateDirectoryButton from "./Buttons/CreateDirectoryButton";
import HomeDirectoryButton from "./Buttons/HomeDirectoryButton";
import { ToolbarWrapper } from "./Toolbar.styles";
const buttons = [
HomeDirectoryButton,
CreateDirectoryButton,
];
export default function Toolbar() {
return (
<>
<ToolbarWrapper shadow="sm">
<Grid>
{buttons.map((Button, index) => (
<Button key={index} />
))}
</Grid>
</ToolbarWrapper>
</>
);
}
이제 다음과 같이 보입니다.
이제 기능을 향상시켜 실제로
HomeDirectoryButton
를 복사/붙여넣고 필요에 따라 변경합니다.// components/Toolbar/Buttons/CreateDirectoryButton.tsximport { Text, ThemeIcon, Tooltip, useMantineTheme } from "@mantine/core";
import { IconCirclePlus } from "@tabler/icons";
import {
ToolbarButtonText,
ToolBarButtonWrapper,
ToolbarIcon,
} from "../Toolbar.styles";
export default function CreateDirectoryButton() {
const theme = useMantineTheme();
return (
<Tooltip
label={"Create New Directory"}
position="bottom"
transition="slide-up">
<ToolBarButtonWrapper>
<ToolbarIcon variant="subtle">
<ThemeIcon
variant="gradient"
gradient={{ from: "indigo", to: "cyan" }}>
<IconCirclePlus size={18} color={theme.white} />
</ThemeIcon>
</ToolbarIcon>
<ToolbarButtonText>
<Text color="blue">Directory</Text>
</ToolbarButtonText>
</ToolBarButtonWrapper>
</Tooltip>
);
}
나는 그것이 최고의 모습은 아니지만 여전히 그렇게 나쁘지는 않다는 것을 압니다 😁
모달 팝업
이제 우리는 디렉토리를 생성하기 위한 폼을 표시하는 팝업을 생성하고 싶으므로 이를 위한 새 구성 요소를 생성해 보겠습니다.
// components/Toolbar/Modals/CreateDirectoryModal.tsx
import { Modal } from "@mantine/core";
export type CreateDirectoryModalProps = {
open: boolean;
onClose: () => void;
};
export default function CreateDirectoryModal({
open,
onClose,
}: CreateDirectoryModalProps) {
return (
<Modal opened={open} onClose={onClose}>
<div>Modal content</div>
</Modal>
);
}
이제 버튼 구성 요소에서 열기/닫기 상태를 만들고 모달을 가져옵니다.
// components/Toolbar/Buttons/CreateDirectoryButton.tsx
import { Text, ThemeIcon, Tooltip, useMantineTheme } from "@mantine/core";
import { IconCirclePlus } from "@tabler/icons";
import { useState } from "react";
import {
ToolbarButtonText,
ToolBarButtonWrapper,
ToolbarIcon,
} from "../Toolbar.styles";
import CreateDirectoryModal from "./CreateDirectoryModal";
export default function CreateDirectoryButton() {
const theme = useMantineTheme();
const [openModal, setOpenModal] = useState(false);
return (
<>
<Tooltip
label={"Create New Directory"}
position="bottom"
transition="slide-up">
<ToolBarButtonWrapper onClick={() => setOpenModal(true)}>
<ToolbarIcon variant="subtle">
<ThemeIcon
variant="gradient"
gradient={{ from: "indigo", to: "cyan" }}>
<IconCirclePlus size={18} color={theme.white} />
</ThemeIcon>
</ToolbarIcon>
<ToolbarButtonText>
<Text color="blue">Directory</Text>
</ToolbarButtonText>
</ToolBarButtonWrapper>
</Tooltip>
<CreateDirectoryModal
open={openModal}
onClose={() => setOpenModal(false)}
/>
</>
);
}
이제 시도해보고 버튼을 클릭하면 모달이 열립니다.
양식을 갖도록 업데이트하거나 모달합시다.
// components/Toolbar/Modals/CreateDirectoryModal.tsx
import { Modal } from "@mantine/core";
import { Form } from "@mongez/react-form";
import SubmitButton from "design-system/components/Form/SubmitButton";
import TextInput from "design-system/components/Form/TextInput";
import { useKernel } from "../../../hooks";
export type CreateDirectoryModalProps = {
open: boolean;
onClose: () => void;
};
export default function CreateDirectoryModal({
open,
onClose,
}: CreateDirectoryModalProps) {
const kernel = useKernel();
return (
<Modal
title={<strong>{kernel.currentDirectoryNode?.path}</strong>}
opened={open}
trapFocus={false}
onClose={onClose}>
<Form>
<h2>Create New Directory</h2>
<TextInput
name="name"
required
autoFocus
placeholder="Please Enter Directory Name"
/>
<div
style={{
textAlign: "end",
marginTop: "1.5rem",
}}>
<SubmitButton>Create</SubmitButton>
</div>
</Form>
</Modal>
);
}
양식 제출 및 유효성 검사를 관리하기 위해 양식 구성 요소를 가져왔으며 양식을 만들기 위해
SubmitButton
및 TextInput
를 가져왔습니다.이제 다음과 같이 보입니다.
이제 Mantine 버튼을 사용하도록
SubmitButton
UI를 업데이트하겠습니다.// design-system/components/Form/SubmitButton.tsx
// 👇🏻 we import the button from Mantine
import { Button } from "@mantine/core";
import { useForm } from "@mongez/react-form";
import { useEffect, useState } from "react";
import Loader from "./../Indicators/Loader";
type SubmitButtonProps = {
children: React.ReactNode;
[key: string]: any;
};
export default function SubmitButton({
children,
...props
}: SubmitButtonProps) {
const [isSubmitting, submitting] = useState(false);
const [isDisabled, disable] = useState(false);
const formProvider = useForm();
useEffect(() => {
if (!formProvider) return;
const onSubmit = formProvider.form.on("submit", () => {
submitting(formProvider.form.isSubmitting());
disable(formProvider.form.isSubmitting());
});
const inValidControls = formProvider.form.on("invalidControls", () => {
disable(true);
});
const validControl = formProvider.form.on("validControls", () => {
disable(false);
});
return () => {
onSubmit.unsubscribe();
validControl.unsubscribe();
inValidControls.unsubscribe();
};
}, [formProvider]);
return (
<>
// 👇🏻 we use the Mantine button instead of the BaseButton
<Button
// 👇🏻 we use the gradient variant
variant="gradient"
gradient={{ from: "blue", to: "cyan" }}
type="submit"
// 👇🏻 we use the loading prop to show the loader
loading={isSubmitting}
{...props}
disabled={isDisabled || isSubmitting}>
{children}
</Button>
</>
);
}
제출 버튼을 위한 것이므로 더 이상 수행하지 않습니다.
이제 Mantine 텍스트 입력을 사용하도록 텍스트 입력을 업데이트하겠습니다.
// design-system/components/Form/BaseInput.tsx
// 👇🏻 we import the Mantine text input
import { Input } from "@mantine/core";
import { FormInputProps, useFormInput } from "@mongez/react-form";
import { requiredRule } from "@mongez/validator";
import InputError from "./InputError";
import InputLabel from "./InputLabel";
export default function BaseInput(props: FormInputProps) {
const {
name,
id,
value,
label,
placeholder,
required,
onChange,
onBlur,
error,
// 👇🏻 extract the autoFocus prop as well to allow focusing on the input
autoFocus,
otherProps,
} = useFormInput(props);
return (
<>
<div className="form-control">
<InputLabel htmlFor={id} required={required}>
{label}
</InputLabel>
// 👇🏻 we use the Mantine text input instead of the native input
<Input
id={id}
name={name}
placeholder={placeholder as string}
onChange={onChange}
onBlur={onBlur as any}
value={value}
// 👇🏻 we use the autoFocus prop to focus on the input
autoFocus={autoFocus}
// 👇🏻 we use the invalid prop to show the input has error
invalid={error !== null}
{...otherProps}
/>
{error && <InputError error={error} />}
</div>
</>
);
}
BaseInput.defaultProps = {
type: "text",
rules: [requiredRule],
};
이제 최종 모달 모양은 다음과 같습니다.
액션
이제 모달로 작업을 마쳤습니다. 이제 양식을 제출하고 디렉토리를 생성하겠습니다.
import { Modal } from "@mantine/core";
import { Form, FormInterface } from "@mongez/react-form";
import SubmitButton from "design-system/components/Form/SubmitButton";
import TextInput from "design-system/components/Form/TextInput";
import React from "react";
import { useKernel } from "../../../hooks";
export type CreateDirectoryModalProps = {
open: boolean;
onClose: () => void;
};
export default function CreateDirectoryModal({
open,
onClose,
}: CreateDirectoryModalProps) {
const kernel = useKernel();
// 👇🏻 we use the onSubmit prop to submit the form
const submitForm = (e: React.FormEvent, form: FormInterface) => {
}
return (
<Modal
title={<strong>{kernel.currentDirectoryNode?.path}</strong>}
opened={open}
trapFocus={false}
onClose={onClose}>
// 👇🏻 we use the onSubmit prop to submit the form
<Form onSubmit={submitForm}>
<h2>Create New Directory</h2>
<TextInput
name="name"
required
autoFocus
placeholder="Please Enter Directory Name"
/>
<div
style={{
textAlign: "end",
marginTop: "1.5rem",
}}>
<SubmitButton>Create</SubmitButton>
</div>
</Form>
</Modal>
);
}
여기서 좋은 점은 입력이 채워질 때까지 양식 제출이 발생하지 않는다는 것입니다. 그렇지 않으면 오류가 표시됩니다.
이제 입력 값만 가져오면 되므로 전체 양식 요소를 보낼 필요가 없습니다.
// 👇🏻 we use the onSubmit prop to submit the form
const submitForm = (e: React.FormEvent, form: FormInterface) => {
const directoryName = form.value("name");
kernel.actions.createDirectory(directoryName);
};
따라서 입력
name
을 사용하여 입력 값을 얻을 수 있습니다. 이제 이를 createDirectory
작업에 전달하고 지금은 기록해 보겠습니다.이제 양식을 제출하면 콘솔에 입력 값이 표시되므로
App
를 입력하면 콘솔에 create directory App
가 표시됩니다.또 다른 작은 변경 사항을 만들어 보겠습니다. 이 디렉터리를 만드는 데 필요한 디렉터리 경로도 전달합니다.
// createDirectory.tsx
import Kernel from "../Kernel";
export default function createDirectory(kernel: Kernel) {
return function create(directoryName: string, directoryPath: string = kernel.currentDirectoryNode?.path as string) {
console.log("create directory", directoryName);
};
}
따라서 두 번째 매개 변수에 디렉터리 경로를 전달할 수 있지만 현재 디렉터리 경로를 기본값으로 설정합니다.
다음 장
다음 장에서는 먼저 백엔드에 디렉토리를 만든 다음 React 프로젝트에서 구현합니다.
기사 저장소
Github Repository에서 챕터 파일을 볼 수 있습니다.
Don't forget the
main
branch has the latest updated code.
지금 어디 있는지 말해줘
이 시리즈를 저와 함께 후속 조치하는 경우 현재 위치와 어려움을 겪고 있는 부분을 알려주시면 최대한 도와드리겠습니다.
살람.
Reference
이 문제에 관하여(React File Manager를 만들어 봅시다. 20장: Create Directory 버튼 만들기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/hassanzohdy/lets-create-a-react-file-manager-chapter-xx-creating-create-directory-button-1a27텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)