React 파일 관리자를 만들어 봅시다. 6장: 디렉터리 및 파일 가져오기
32168 단어 typescriptmongezreact
워크플로우
파일 관리자가 열리면
root
경로를 로드한 다음 사이드바에 해당 디렉토리를 나열하고 오른쪽에 해당 내용(파일 및 디렉토리)을 나열합니다.따라서 다음 상태가 필요합니다.
Loading
파일 관리자가 디렉토리를 로드 중인지 확인하는 상태입니다. currentDirectoryNode
: 현재 로드된 디렉토리 노드를 포함하는 상태입니다. 지금은 그게 다입니다. 실제로 작동하는 것을 봅시다.
// FileManager.tsx
export default function FileManager({
open,
onClose,
rootPath,
}: FileManagerProps) {
const [isLoading, setIsLoading] = useState(true);
const [currentDirectoryNode, setCurrentDirectoryNode] = useState<Node>();
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: "/",
};
기본 props 객체에
rootPath
를 추가하고 앞에서 언급한 것처럼 두 가지 상태를 생성했습니다.이제 파일 관리자의 새 인스턴스를 만들어
ref
에 저장해 보겠습니다.import { Grid, Modal } from "@mantine/core";
import BaseFileManager from "app/file-manager/utils/FileManager";
import { useRef, useState } from "react";
import Content from "./Content";
import { BodyWrapper } from "./FileManager.styles";
import { FileManagerProps } from "./FileManager.types";
import Sidebar from "./Sidebar";
import Toolbar from "./Toolbar";
import { Node } from "../../types/FileManager.types";
export default function FileManager({
open,
onClose,
rootPath,
}: FileManagerProps) {
const [isLoading, setIsLoading] = useState(true);
const [currentDirectoryNode, setCurrentDirectoryNode] = useState<Node>();
const fileManagerRef = useRef(new BaseFileManager());
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: "/",
};
이름을
BaseFileManager
로 변경하여 구성 요소 자체와 혼동하지 않도록 했습니다.실제로
current
키를 직접 파괴하여 ref를 향상시킬 수 있습니다.- const fileManagerRef = useRef(new BaseFileManager());
+ const { current: fileManager } = useRef(new BaseFileManager());
다음으로 루트 경로를 로드할
useEffect
후크를 생성해 보겠습니다.import { Node } from "../../types/FileManager.types";
export default function FileManager({
open,
onClose,
rootPath,
}: FileManagerProps) {
const [isLoading, setIsLoading] = useState(true);
const [currentDirectoryNode, setCurrentDirectoryNode] = useState<Node>();
const { current: fileManager } = useRef(new BaseFileManager());
// load root directory
useEffect(() => {
if (!rootPath) return;
setIsLoading(true);
fileManager.load(rootPath).then(() => {
setIsLoading(false);
setCurrentDirectoryPath(rootPath);
});
}, [rootPath, fileManager]);
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: "/",
};
이제
rootPath
를 종속성 배열에 추가했으므로 useEffect
가 변경되면 rootPath
가 호출되고 지정된 경로를 현재 디렉터리로 로드하므로 load
도 호출됩니다.load
메서드로 이동하기 전에 파일 관리자가 열려 있지 않으면 로드를 무시한다는 또 다른 조건을 추가해 보겠습니다. // load root directory
useEffect(() => {
if (!rootPath || !open) return;
setIsLoading(true);
fileManager.load(rootPath).then(directoryNode => {
setIsLoading(false);
currentDirectoryNode(directoryNode);
});
}, [rootPath, fileManager, open]);
로드 방법 생성
load
메서드는 지정된 경로를 로드하고 경로가 로드되면 해결될 약속을 반환하며 로드된 디렉토리와 함께 Node
도 반환합니다.또한 파일 관리자에서 루트 경로를 정의해야 하므로
setRootPath
메서드를 생성합니다.
// file-manager/utils/FileManager.ts
import { Node } from "../types/FileManager.types";
export default class FileManager {
/**
* Root path
*/
protected rootPath = "/";
/**
* Current directory path
*/
protected currentDirectoryPath = "/";
/**
* Current directory node
*/
protected currentDirectoryNode?: Node;
/**
* Set root path
*/
public setRootPath(rootPath: string): FileManager {
this.rootPath = rootPath;
return this;
}
}
FileManagerService
로 이동하여 여기에서 새 인스턴스를 만들고 내보내서 직접 사용할 수 있도록 합시다.파일 끝에서 인스턴스를 내보냅니다.
// file-manager-service.ts
const fileManagerService = new FileManagerService();
export default fileManagerService;
이제
load
에서 FileManager
메서드를 정의해 보겠습니다.// FileManager.ts
import fileManagerService from "../services/file-manager-service";
import { Node } from "../types/FileManager.types";
export default class FileManager {
/**
* Root path
*/
protected rootPath = "/";
/**
* Current directory path
*/
protected currentDirectoryPath = "/";
/**
* Current directory node
*/
protected currentDirectoryNode?: Node;
/**
* Set root path
*/
public setRootPath(rootPath: string): FileManager {
this.rootPath = rootPath;
return this;
}
/**
* Load the given path
*/
public load(path: string): Promise<Node> {
return new Promise((resolve, reject) => {
fileManagerService
.list(path)
.then(response => {
this.currentDirectoryPath = path;
this.currentDirectoryNode = response.data.node;
resolve(this.currentDirectoryNode as Node);
})
.catch(reject);
});
}
}
list
에서 FileManagerService
메서드를 사용하여 디렉터리 노드를 가져온 다음 currentDirectoryNode
에 저장하고 반환했습니다.그러나
list
메서드를 약간 수정해야 합니다. 백엔드에서 직접 내부에 나열된 모든 자식을 포함하는 단일 노드를 반환해야 백엔드에서 처리할 수 있습니다.import FileManagerServiceInterface from "../types/FileManagerServiceInterface";
import {
+ newNode,
- listNodes
} from "../utils/data";
export class FileManagerService implements FileManagerServiceInterface {
/**
* {@inheritDoc}
*/
public list(directoryPath: string): Promise<any> {
return new Promise(resolve => {
resolve({
data: {
- node: listNodes(),
+ node: newNode(),
},
});
});
}
}
const fileManagerService = new FileManagerService();
export default fileManagerService;
load
메서드로 돌아가서 로드 약속을 위해 확인될 현재 디렉터리 노드도 정의했습니다.이제
FileManager.tsx
구성 요소와 console.logcurrentDirectoryNode
로 이동하여 무엇이 반환되는지 확인합니다. ...
const { current: fileManager } = useRef(new BaseFileManager());
console.log(currentDirectoryNode);
무작위로 생성되기 때문에 항상 디렉토리가 있는지 확인하기 위해 디렉토리에 대해 또 다른 생성 노드를 만들어 봅시다.
// utils/data.ts
export function newNode(): Node {
const isDirectory = faker.datatype.boolean();
const node: Node = {
name: isDirectory ? faker.system.directoryPath() : faker.system.fileName(),
path: faker.system.filePath(),
size: faker.datatype.number({ min: 1, max: 100000 }),
isDirectory,
};
if (node.isDirectory) {
node.children = listNodes(1, 3);
}
return node;
}
export function newDirectoryNode() {
const node = newNode();
node.children = listNodes(faker.datatype.number({ min: 3, max: 4 }), 5);
node.name = faker.system.directoryPath();
node.isDirectory = true;
return node;
}
또한
listNodes
에서 최소값과 최대값을 허용하도록 약간 수정하여 항상 최소 3개의 하위 항목이 있는 디렉토리를 갖도록 했습니다.이제
newDirectoryNode
대신 newNode
를 호출하도록 서비스 클래스를 업데이트하겠습니다.- import { newNode } from "../utils/data";
+ import { newDirectoryNode } from "../utils/data";
return new Promise(resolve => {
resolve({
data: {
- node: newNode(),
+ node: newDirectoryNode(),
},
});
});
여기에서 잠시 멈추고 다음 기사에서 계속하겠습니다. 헷갈린다면 아래 리포지토리에서 최종 코드를 읽은 다음 기사를 다시 읽으십시오.
다음 기사는 사이드바에 디렉토리를 나열하는 방법에 관한 것입니다.
기사 저장소
Github Repository에서 챕터 파일을 볼 수 있습니다.
Don't forget the
main
branch has the latest updated code.
살람.
Reference
이 문제에 관하여(React 파일 관리자를 만들어 봅시다. 6장: 디렉터리 및 파일 가져오기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/hassanzohdy/lets-create-a-react-file-manager-chapter-vi-fetching-directories-and-files-5e11텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)