React 파일 관리자를 만들어 봅시다. 7장: 사이드바 나열
31741 단어 typescriptmongezreact
그러나 이 작업을 수행하기 전에 나중에 선택한 디렉토리를 로드하는 함수가 필요하므로 파일 관리자에서 디렉토리 로드를 개선해 보겠습니다. 따라서
load
구성 요소에 FileManager
함수를 생성해 보겠습니다.// FileManager.tsx
...
// load the given directory path
const load = (path: string) => {
setIsLoading(true);
fileManager
.load(path)
.then(node => {
setCurrentDirectoryNode(node);
})
.finally(() => {
setIsLoading(false);
});
};
// load root directory
useEffect(() => {
if (!rootPath || !open) return;
setIsLoading(true);
fileManager.load(rootPath).then(directoryNode => {
setIsLoading(false);
setCurrentDirectoryNode(directoryNode);
});
}, [rootPath, fileManager, open]);
로드 함수를 생성하고 이제
useEffect
후크에서 호출하여 루트 디렉토리를 로드해야 합니다.// FileManager.tsx
// load root directory
useEffect(() => {
if (!rootPath || !open) return;
load(rootPath);
}, [rootPath, fileManager, open]);
이제 eslint는 종속성 배열에 없는
load
함수에 대해 불평할 것입니다. 따라서 이를 추가하지만 효과를 여러 번 다시 로드하지 않도록 useCallback
로 래핑해야 합니다.// FileManager.tsx
// load the given directory path
const load = useCallback(
(path: string) => {
setIsLoading(true);
fileManager
.load(path)
.then(node => {
setCurrentDirectoryNode(node);
})
.finally(() => {
setIsLoading(false);
});
},
[fileManager],
);
// load root directory
useEffect(() => {
if (!rootPath || !open) return;
load(rootPath);
}, [rootPath, fileManager, open, load]);
한 가지 더 해야 할 일은
rootDirectoryNode
구성 요소에서 사용할 수 있도록 Sidebar
를 상태로 저장해야 한다는 것입니다.// FileManager.tsx
...
const [currentDirectoryNode, setCurrentDirectoryNode] = useState<Node>();
const [rootDirectoryNode, setRootDirectoryNode] = useState<Node>();
...
// load the given directory path
const load = useCallback(
(path: string, isRoot = false) => {
setIsLoading(true);
fileManager
.load(path)
.then(node => {
setCurrentDirectoryNode(node);
if (isRoot) {
setRootDirectoryNode(node);
}
})
.finally(() => {
setIsLoading(false);
});
},
[fileManager],
);
// load root directory
useEffect(() => {
if (!rootPath || !open) return;
load(rootPath, true);
}, [rootPath, fileManager, open, load]);
이제 FileManager는 다음과 같이 표시됩니다.
// FileManager.tsx
import { Grid, Modal } from "@mantine/core";
import BaseFileManager from "app/file-manager/utils/FileManager";
import { useCallback, useEffect, useRef, useState } from "react";
import { Node } from "../../types/FileManager.types";
import Content from "./Content";
import { BodyWrapper } from "./FileManager.styles";
import { FileManagerProps } from "./FileManager.types";
import Sidebar from "./Sidebar";
import Toolbar from "./Toolbar";
export default function FileManager({
open,
onClose,
rootPath,
}: FileManagerProps) {
const [isLoading, setIsLoading] = useState(true);
const [currentDirectoryNode, setCurrentDirectoryNode] = useState<Node>();
const [rootDirectoryNode, setRootDirectoryNode] = useState<Node>();
const { current: fileManager } = useRef(new BaseFileManager());
// load the given directory path
const load = useCallback(
(path: string, isRoot = false) => {
setIsLoading(true);
fileManager.load(path).then(node => {
setCurrentDirectoryNode(node);
setIsLoading(false);
if (isRoot) {
setRootDirectoryNode(node);
}
});
},
[fileManager],
);
// load root directory
useEffect(() => {
if (!rootPath || !open) return;
load(rootPath, true);
}, [rootPath, fileManager, open, load]);
return (
<>
<Modal size="xl" opened={open} onClose={onClose}>
<Toolbar />
<BodyWrapper>
<Grid>
<Grid.Col span={3}>
<Sidebar />
</Grid.Col>
<Grid.Col span={9}>
<Content />
</Grid.Col>
</Grid>
</BodyWrapper>
</Modal>
</>
);
}
FileManager.defaultProps = {
rootPath: "/",
};
사이드바
이제 루트 디렉토리 내용을 표시해야 하므로
Sidebar
구성 요소를 업데이트하고 루트 노드에 전달해야 합니다.// Sidebar.tsx
import { Card } from "@mantine/core";
import { Node } from "../../../types/FileManager.types";
export type SidebarProps = {
rootDirectory?: Node;
};
export default function Sidebar({ rootDirectory }: SidebarProps) {
return (
<>
<Card shadow="sm">
<div>Sidebar</div>
</Card>
</>
);
}
이제 하위 콘텐츠를 표시하기 위해 루트 디렉터리를 반복해 보겠습니다. 그러나 여기에는 문제가 있습니다. 루트 디렉터리인 경우에만 루트 디렉터리의 하위 항목을 표시해야 합니다.
// Sidebar.tsx
import { Card } from "@mantine/core";
import { useMemo } from "react";
import { Node } from "../../../types/FileManager.types";
export type SidebarProps = {
rootDirectory?: Node;
};
export default function Sidebar({ rootDirectory }: SidebarProps) {
const rootChildren = useMemo(() => {
return rootDirectory?.children?.filter(child => child.isDirectory);
}, [rootDirectory]);
if (!rootDirectory) return null;
return (
<>
<Card shadow="sm">
<div>Sidebar</div>
</Card>
</>
);
}
간단한 필터를 사용하여 루트 디렉토리 자식을 저장하고
isDirectory
속성이 true
로 설정된 자식 노드만 가져오는 메모를 만듭니다.이제
FileManager
구성 요소로 돌아가서 rootDirectoryNode
를 Sidebar
구성 요소로 전달해 보겠습니다.// FileManager.tsx
<Grid.Col span={3}>
- <Sidebar />
+ <Sidebar rootDirectory={rootDirectoryNode} />
</Grid.Col>
이제 다음과 같은 내용이 표시됩니다.
사이드바 노드 표시
코드를 약간 개선하고 각 노드에 대한 사이드바 노드를 생성하여 더 많은 컨트롤을 얻을 수 있고 코드가 덜 복잡해집니다. 이름을
SidebarNode.tsx
로 지정하고 Sidebar
의 동일한 디렉토리에 생성합니다.// SidebarNode.tsx
import { Node } from "../../../types/FileManager.types";
export type SidebarNodeProps = {
node: Node;
};
export default function SidebarNode({ node }: SidebarNodeProps) {
return (
<>
<div>{node.name}</div>
</>
);
}
이제
Sidebar
구성 요소를 업데이트하여 각 노드에 대해 SidebarNode
를 표시해 보겠습니다.// Sidebar.tsx
import { Card } from "@mantine/core";
import { useMemo } from "react";
import { Node } from "../../../types/FileManager.types";
import SidebarNode from "./SidebarNode";
export type SidebarProps = {
rootDirectory?: Node;
};
export default function Sidebar({ rootDirectory }: SidebarProps) {
const rootChildren = useMemo(() => {
return rootDirectory?.children?.filter(child => child.isDirectory);
}, [rootDirectory]);
if (!rootDirectory) return null;
return (
<>
<Card shadow="sm">
{rootChildren?.map(child => (
<SidebarNode key={child.path} node={child} />
))}
</Card>
</>
);
}
이제 다음과 같이 표시됩니다.
다음 기사에서는 아이콘 추가와 같이 사이드바를 더 개선하고 사이드바 상단에 표시할 홈 루트도 추가할 것입니다.
기사 저장소
Github Repository에서 챕터 파일을 볼 수 있습니다.
Don't forget the
main
branch has the latest updated code.
살람.
Reference
이 문제에 관하여(React 파일 관리자를 만들어 봅시다. 7장: 사이드바 나열), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/hassanzohdy/lets-create-a-react-file-manager-chapter-vii-listing-sidebar-3g7d텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)