Let's create a React File Manager Chapter IX: FileManager Hook And Context
Tags: react, typescript, mongez, javascript
Published: 2022-09-13 19:21:12

---
title: Let's create a React File Manager Chapter IX: FileManager Hook And Context
published: true
description: 
series: File Manager React Mongez
tags: react, typescript, mongez, javascript
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/314szylzr6lwrc0bizyb.png
# Use a ratio of 100:42 for best results.
---

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:

```tsx
// 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.

```tsx
// 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:

```tsx
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.

```tsx
// 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](https://github.com/hassanzohdy/file-manager-react/tree/9-filemanager-context-and-hook)

> 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.