Let's create a React File Manager Chapter IX: FileManager Hook And Context
Hasan Zohdy
Posted on September 13, 2022
In our last article, we updated the sidebar node to show the directory name and icon, but we need first a way to get the file manager to be accessed from anywhere in the file manager components list, let's make a context for it.
FileManager Context
Let's make a context to capture current file manager easily.
Create contexts/FileManagerContext.tsx
file and add the following code:
// contexts/FileManager.context.tsx
import { createContext } from "react";
import FileManager from "../utils/FileManager";
const FileManagerContext = createContext<FileManager | null>(null);
export default FileManagerContext;
Now let's wrap our FileManager
component with the context provider.
// FileManager.tsx
import { Grid, Modal } from "@mantine/core";
import BaseFileManager from "app/file-manager/utils/FileManager";
import { useCallback, useEffect, useRef, useState } from "react";
import FileManagerContext from "../../contexts/FileManagerContext";
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 (
<FileManagerContext.Provider value={fileManager}>
<Modal size="xl" opened={open} onClose={onClose}>
<Toolbar />
<BodyWrapper>
<Grid>
<Grid.Col span={3}>
<Sidebar rootDirectory={rootDirectoryNode} />
</Grid.Col>
<Grid.Col span={9}>
<Content />
</Grid.Col>
</Grid>
</BodyWrapper>
</Modal>
</FileManagerContext.Provider>
);
}
FileManager.defaultProps = {
rootPath: "/",
};
File Manager hook
So we created the context, now let's create a simple hook to get the file manager from anywhere in the component.
Create hooks/useFileManager.ts
file and add the following code:
import { useContext } from "react";
import FileManagerContext from "../contexts/FileManagerContext";
export default function useFileManager() {
const fileManager = useContext(FileManagerContext);
if (!fileManager) {
throw new Error("useFileManager must be used within FileManagerProvider");
}
return fileManager;
}
From this point we can now use the useFileManager
hook to get the file manager from anywhere in any of our file manager components.
Now we are ready to point to active sidebar node, which will be done in the next chapter.
File Manager Public Properties
For quick access, we'll make the properties public to quickly access it.
// file-manager/utils/FileManager.ts
import fileManagerService from "../services/file-manager-service";
import { Node } from "../types/FileManager.types";
export default class FileManager {
/**
* Root path
*/
public rootPath = "/";
/**
* Current directory path
*/
public currentDirectoryPath = "/";
/**
* Current directory node
*/
public 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);
});
}
}
Article Repository
You can see chapter files in Github Repository
Don't forget the
main
branch has the latest updated code.
Tell me where you are now
If you're following up with me this series, tell me where are you now and what you're struggling with, i'll try to help you as much as i can.
Salam.
Posted on September 13, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.