26-React 파일 관리자 26장: 노드 감시자
45788 단어 typescriptmongezreactjavascript
디렉토리 생성
이제
createDirectory
작업으로 돌아가서 디렉토리가 생성되면 커널 트리를 업데이트해야 합니다.// createDirectory.ts
import { toastLoading } from "design-system/components/Toast";
import Kernel from "../Kernel";
import fileManagerService from "../services/file-manager-service";
export default function createDirectory(kernel: Kernel) {
return function create(
directoryName: string,
directoryPath: string = kernel.currentDirectoryNode?.path as string,
) {
return new Promise((resolve, reject) => {
const loader = toastLoading(
"Creating directory...",
"We are creating your directory, please wait a moment.",
);
fileManagerService
.createDirectory(directoryName, directoryPath)
.then(response => {
loader.success("Success!", "Your directory has been created.");
👉🏻 kernel.tree.setNode(response.data.node);
resolve(response.data.node);
})
.catch(error => {
loader.error("Error", error.response.data.error);
reject(error);
});
});
};
}
이제 우리는 커널 트리에게 이 노드가 속한 위치를 설정하도록 지시했습니다. 그러면 트리가 업데이트될 것입니다.
useNodeWatcher
이제 트리의 변경 사항을 감시하고 변경 사항이 감지되면 트리를 업데이트하는 후크를 생성해 보겠습니다.
// hooks/useNodeWatcher.ts
import { Node } from "app/file-manager/Kernel";
import { useEffect, useState } from "react";
import useKernel from "./useKernel";
export default function useWatchNodeChange(node?: Node) {
const kernel = useKernel();
// Store the node internally in a state
const [internalNode, setNode] = useState<Node | undefined>(node);
useEffect(() => {
// watch for node change
const event = kernel.on("nodeChange", (newNode: Node) => {
// if the updated node is the same as the one we are watching
// then update the internal node
if (newNode.path === internalNode?.path) {
setNode({ ...newNode });
}
});
return () => event.unsubscribe();
}, [internalNode, kernel]);
useEffect(() => {
setNode(node);
}, [node]);
return internalNode;
}
여기에는 설명할 것이 없습니다. 노드를 상태에 저장하고 커널의 변경 사항을 감시하고 있습니다. 업데이트된 노드가 우리가 보고 있는 노드와 동일하면 내부 노드를 업데이트합니다.
노드 목록 업데이트
이미 디렉터리 변경 이벤트를 수신하고 있으므로 노드 목록을 업데이트하기 위해 노드 자체도 감시해야 합니다.
// NodesList.tsx
import { Grid } from "@mantine/core";
import {
useCurrentDirectoryNode,
useNodeWatcher,
} from "app/file-manager/hooks";
import { DirectoryNode, FileNode } from "./ContentNode";
export default function NodesList() {
const currentDirectoryNode = useCurrentDirectoryNode();
const node = useNodeWatcher(currentDirectoryNode);
return (
<>
<Grid>
{node?.directories?.map(node => (
<Grid.Col key={node.path} span={2}>
<DirectoryNode node={node} />
</Grid.Col>
))}
{node?.files?.map(node => (
<Grid.Col key={node.path} span={2}>
<FileNode node={node} />
</Grid.Col>
))}
</Grid>
</>
);
}
prepareNode
메소드 덕분에 노드에서 파일과 디렉토리를 수집하는 메모를 제거했습니다.그런 다음 노드의 변경 사항을 감시하기 위해
useNodeWatcher
후크를 추가했습니다.사이드바 업데이트 중
루트도 노드로 간주되므로 루트 노드의 변경 사항을 감시하려면 사이드바를 업데이트해야 합니다.
// Sidebar.tsx
import {
Card,
ScrollArea,
Skeleton,
ThemeIcon,
useMantineTheme,
} from "@mantine/core";
import { IconFolder, IconHome2 } from "@tabler/icons";
import { useKernel, useLoading } from "app/file-manager/hooks";
import useWatchNodeChange from "../../hooks/useNodeWatcher";
import { SidebarWrapper } from "./Sidebar.styles";
import SidebarNode from "./SidebarNode";
export default function Sidebar() {
const isLoading = useLoading();
const theme = useMantineTheme();
// get the kernel
const kernel = useKernel();
// watch for the root node for change
const rootNode = useWatchNodeChange(kernel.rootNode);
if (isLoading) {
return (
<Card shadow={"sm"}>
<SidebarWrapper>
<Skeleton height={8} mt={6} radius="xl" />
<Skeleton height={12} mt={6} width="80%" radius="sm" />
<Skeleton height={8} mt={6} width="60%" radius="xl" />
<Skeleton height={8} mt={6} radius="xl" />
<Skeleton height={12} mt={6} width="80%" radius="sm" />
<Skeleton height={8} mt={6} width="60%" radius="xl" />
<Skeleton height={8} mt={6} radius="xl" />
<Skeleton height={12} mt={6} width="80%" radius="sm" />
<Skeleton height={8} mt={6} width="60%" radius="xl" />
<Skeleton height={8} mt={6} radius="xl" />
<Skeleton height={12} mt={6} width="80%" radius="sm" />
<Skeleton height={8} mt={6} width="60%" radius="xl" />
</SidebarWrapper>
</Card>
);
}
// if no root node yet, return null
if (!rootNode) return null;
return (
<Card shadow="sm">
<SidebarWrapper>
<ScrollArea type="auto" style={{ height: "300px" }}>
<SidebarNode
node={rootNode}
icon={
<ThemeIcon variant="light" color={theme.colors.lime[1]}>
<IconHome2 size={16} color={theme.colors.lime[9]} />
</ThemeIcon>
}
/>
{rootNode.directories?.map(child => (
<SidebarNode
navProps={{
pl: 25,
}}
key={child.path}
icon={
<ThemeIcon variant="light" color={theme.colors.blue[1]}>
<IconFolder size={16} color={theme.colors.blue[5]} />
</ThemeIcon>
}
node={child}
/>
))}
</ScrollArea>
</SidebarWrapper>
</Card>
);
}
루트 노드의 변경 사항을 감시하기 위해
useWatchNodeChange
후크를 추가했습니다.사이드바 스켈레톤을 별도의 구성 요소로 이동해 보겠습니다.
// SidebarSkeleton.tsx
import { Card, Skeleton } from "@mantine/core";
export default function SidebarSkeleton() {
return (
<Card shadow={"sm"}>
<Skeleton height={8} mt={6} radius="xl" />
<Skeleton height={12} mt={6} width="80%" radius="sm" />
<Skeleton height={8} mt={6} width="60%" radius="xl" />
<Skeleton height={8} mt={6} radius="xl" />
<Skeleton height={12} mt={6} width="80%" radius="sm" />
<Skeleton height={8} mt={6} width="60%" radius="xl" />
<Skeleton height={8} mt={6} radius="xl" />
<Skeleton height={12} mt={6} width="80%" radius="sm" />
<Skeleton height={8} mt={6} width="60%" radius="xl" />
<Skeleton height={8} mt={6} radius="xl" />
<Skeleton height={12} mt={6} width="80%" radius="sm" />
<Skeleton height={8} mt={6} width="60%" radius="xl" />
</Card>
);
}
이제 사이드바 구성 요소는 다음과 같습니다.
// Sidebar.tsx
import { Card, ScrollArea, ThemeIcon, useMantineTheme } from "@mantine/core";
import { IconFolder, IconHome2 } from "@tabler/icons";
import { useKernel, useLoading } from "app/file-manager/hooks";
import useWatchNodeChange from "../../hooks/useNodeWatcher";
import { SidebarWrapper } from "./Sidebar.styles";
import SidebarNode from "./SidebarNode";
import SidebarSkeleton from "./SidebarSkeleton";
export default function Sidebar() {
const isLoading = useLoading();
const theme = useMantineTheme();
// get the kernel
const kernel = useKernel();
// watch for the root node for change
const rootNode = useWatchNodeChange(kernel.rootNode);
if (isLoading) return <SidebarSkeleton />;
// if no root node yet, return null
if (!rootNode) return null;
return (
<Card shadow="sm">
<SidebarWrapper>
<ScrollArea type="auto" style={{ height: "300px" }}>
<SidebarNode
node={rootNode}
icon={
<ThemeIcon variant="light" color={theme.colors.lime[1]}>
<IconHome2 size={16} color={theme.colors.lime[9]} />
</ThemeIcon>
}
/>
{rootNode.directories?.map(child => (
<SidebarNode
navProps={{
pl: 25,
}}
key={child.path}
icon={
<ThemeIcon variant="light" color={theme.colors.blue[1]}>
<IconFolder size={16} color={theme.colors.blue[5]} />
</ThemeIcon>
}
node={child}
/>
))}
</ScrollArea>
</SidebarWrapper>
</Card>
);
}
다음 장
다음 장에서는 노드 선택 알고리즘을 만들기 시작합니다.
기사 저장소
Github Repository에서 챕터 파일을 볼 수 있습니다.
Don't forget the
main
branch has the latest updated code.
지금 어디 있는지 말해줘
이 시리즈를 저와 함께 후속 조치하는 경우 현재 위치와 어려움을 겪고 있는 부분을 알려주시면 최대한 도와드리겠습니다.
살람.
Reference
이 문제에 관하여(26-React 파일 관리자 26장: 노드 감시자), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/hassanzohdy/26-react-file-manager-chapter-xxvi-the-node-watcher-4mn0텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)