Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions docs/hooks/useDownloadBlob.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
tags:
- hook
---

# `useDownloadBlob` Hook

`useDownloadBlob` hook is used to directly download a file as bytes from Firebase Storage. Instead of [`useDownloadLink` hook](./useDownloadLink.md), this hook might be useful to process a file byte by byte instead of directly downloading to the user's machine.

A very simple example would be:

```typescript
const reference = ref(storage, "path/to/remote/file.png");
const { dispatch } = useDownloadBlob({ reference });
const blob = await dispatch(file);
```

!!! warning
`useDownloadBlob` is lazy by default and will not do anything until you use `dispatch` function.

You can get the state of the progress with this example.

```typescript
const { state } = useDownloadBlob({ reference });
const blob = await dispatch();
// `state` is "ready" | "loading" | "done"
```

`dispatch` method will return an instance of [`Blob`][BlobDoc], but additionally, you can also listen to [`Blob`][BlobDoc] from `useDownloadBlob` hook as well:

```typescript
const { blob } = useDownloadBlob({ reference });
// blob updates and rerenders when the state is `"done"`
// until then, it is `undefined`
await dispatch();
```

## Input Parameters

Input parameters for `useDownloadBlob` hook is as follows:

| Name | Type | Description | Required | Default Value |
|---|---|---|---|---|
| `reference` | [`firebase/storage/StorageReference`][StorageReferenceRefDoc] | Reference to a file in Storage. | ✅ | - |

## Return Type

`useDownloadBlob` hook returns an object with properties as below:

| Name | Type | Description |
|---|---|---|
| `blob` | [`Blob`][BlobDoc] or `undefined` | The blob of remote file to read. `undefined` if the `state` is not `"done"`. |
| `state` | `"ready" | "loading" | "done"` | The state of the process. |
| `dispatch` | `(maxDownloadSizeBytes? number) => Promise<string>` | A callback to start the process and return the link. You can also define how many bytes to download at most. |

[StorageReferenceRefDoc]: https://firebase.google.com/docs/reference/js/storage.storagereference
[BlobDoc]: https://developer.mozilla.org/en-US/docs/Web/API/Blob
57 changes: 57 additions & 0 deletions docs/hooks/useDownloadBytes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
tags:
- hook
---

# `useDownloadBytes` Hook

`useDownloadBytes` hook is used to directly download a file as bytes from Firebase Storage. Instead of [`useDownloadLink` hook](./useDownloadLink.md), this hook might be useful to process a file byte by byte instead of directly downloading to the user's machine.

A very simple example would be:

```typescript
const reference = ref(storage, "path/to/remote/file.png");
const { dispatch } = useDownloadBytes({ reference });
const bytes = await dispatch(file);
```

!!! warning
`useDownloadBytes` is lazy by default and will not do anything until you use `dispatch` function.

You can get the state of the progress with this example.

```typescript
const { state } = useDownloadBytes({ reference });
const bytes = await dispatch();
// `state` is "ready" | "loading" | "done"
```

`dispatch` method will return an instance of [`Blob`][BlobDoc], but additionally, you can also listen to [`Blob`][BlobDoc] from `useDownloadBytes` hook as well:

```typescript
const { bytes } = useDownloadBytes({ reference });
// bytes updates and rerenders when the state is `"done"`
// until then, it is `undefined`
await dispatch();
```

## Input Parameters

Input parameters for `useDownloadBytes` hook is as follows:

| Name | Type | Description | Required | Default Value |
|---|---|---|---|---|
| `reference` | [`firebase/storage/StorageReference`][StorageReferenceRefDoc] | Reference to a file in Storage. | ✅ | - |

## Return Type

`useDownloadBytes` hook returns an object with properties as below:

| Name | Type | Description |
|---|---|---|
| `bytes` | [`ArrayBuffer`][ArrayBufferRefDoc] or `undefined` | The bytes of remote file to read. `undefined` if the `state` is not `"done"`. |
| `state` | `"ready" | "loading" | "done"` | The state of the process. |
| `dispatch` | `(maxDownloadSizeBytes? number) => Promise<string>` | A callback to start the process and return the link. You can also define how many bytes to download at most. |

[StorageReferenceRefDoc]: https://firebase.google.com/docs/reference/js/storage.storagereference
[ArrayBufferRefDoc]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer
19 changes: 17 additions & 2 deletions docs/storage/downloading-a-file.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,20 @@

You can use one of the following ways to download a file from Firebase Storage:

- [`useDownloadLink` hook](../hooks/useDownloadLink.md)
- [`StorageDownloadLink` component](../components/StorageDownloadLink.md)
- [`useDownloadLink` hook](../hooks/useDownloadLink.md) to get the link to download
- [`useDownloadBlob` hook](../hooks/useDownloadBlob.md) to directly download the bytes to process it yourself
- [`useDownloadBytes` hook](../hooks/useDownloadBytes.md) to directly download the bytes to process it yourself
- [`StorageDownloadLink` component](../components/StorageDownloadLink.md)

## `useDownloadBlob` vs. `useDownloadBytes`

`useDownloadBlob` uses [`getBlob`][getBlobRefDoc] function in Firebase Storage under the hood while `useDownloadBytes` uses [`getBytes`][getBytesRefDoc].

So, `useDownloadBlob` returns [`Blob`][BlobRef] as `useDownloadBytes` returns [`ArrayBuffer`][ArrayBufferRefDoc].

Generally speaking, both data types represent array of bytes but have subtle differences. You can refer to [this Stackoverflow answer](https://stackoverflow.com/a/39951543/2926992) to learn about the difference.

[getBlobRefDoc]: https://firebase.google.com/docs/reference/js/storage#getblob
[getBytesRefDoc]: https://firebase.google.com/docs/reference/js/storage#getbytes
[BlobRef]: https://developer.mozilla.org/en-US/docs/Web/API/Blob
[ArrayBufferRefDoc]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer
2 changes: 2 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ nav:
- hooks/useUploadFile.md
- hooks/useUploadFileResumable.md
- hooks/useDownloadLink.md
- hooks/useDownloadBlob.md
- hooks/useDownloadBytes.md
- Components:
- Firestore:
- components/FirestoreDocument.md
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "firereact",
"version": "0.6.1",
"version": "0.6.2",
"description": "React hooks, components and utils for Firebase",
"type": "module",
"main": "dist/index.cjs.js",
Expand Down
4 changes: 4 additions & 0 deletions src/storage/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ export * from "./useUploadFileResumable";
export * from "./useDownloadLink";

export * from "./StorageDownloadLink";

export * from "./useDownloadBlob";

export * from "./useDownloadBytes";
17 changes: 17 additions & 0 deletions src/storage/useDownloadBlob.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) 2024 Eray Erdin
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT

import { renderHook } from "@testing-library/react";
import { ref } from "firebase/storage";
import { useDownloadBlob } from ".";
import { storage } from "../firebase";

const reference = ref(storage, "files/README.md");

it("initially, useDownloadBlob hook should have ready state", async () => {
const { result } = renderHook(() => useDownloadBlob({ reference }));
const { state } = result.current;
expect(state).toBe("ready");
});
38 changes: 38 additions & 0 deletions src/storage/useDownloadBlob.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) 2024 Eray Erdin
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT

import { StorageReference, getBlob } from "firebase/storage";
import { useState } from "react";

type UseDownloadBlobParams = {
reference: StorageReference;
};

type UseDownloadBlobState = "ready" | "loading" | "done";
type UseDownloadBlobDispatcher = (
maxDownloadSizeBytes?: number,
) => Promise<Blob>;
type UseDownloadBlob = {
blob: Blob | undefined;
state: UseDownloadBlobState;
dispatch: UseDownloadBlobDispatcher;
};

export const useDownloadBlob = ({
reference,
}: UseDownloadBlobParams): UseDownloadBlob => {
const [state, setState] = useState<UseDownloadBlobState>("ready");
const [blob, setBlob] = useState<Blob | undefined>(undefined);

const dispatch: UseDownloadBlobDispatcher = async (maxDownloadSizeBytes) => {
setState("loading");
const blob = await getBlob(reference, maxDownloadSizeBytes);
setState("done");
setBlob(blob);
return blob;
};

return { blob, state, dispatch };
};
17 changes: 17 additions & 0 deletions src/storage/useDownloadBytes.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) 2024 Eray Erdin
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT

import { renderHook } from "@testing-library/react";
import { ref } from "firebase/storage";
import { useDownloadBytes } from ".";
import { storage } from "../firebase";

const reference = ref(storage, "files/README.md");

it("initially, useDownloadBytes hook should have ready state", async () => {
const { result } = renderHook(() => useDownloadBytes({ reference }));
const { state } = result.current;
expect(state).toBe("ready");
});
38 changes: 38 additions & 0 deletions src/storage/useDownloadBytes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) 2024 Eray Erdin
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT

import { StorageReference, getBytes } from "firebase/storage";
import { useState } from "react";

type UseDownloadBytesParams = {
reference: StorageReference;
};

type UseDownloadBytesState = "ready" | "loading" | "done";
type UseDownloadBytesDispatcher = (
maxDownloadSizeBytes?: number,
) => Promise<ArrayBuffer>;
type UseDownloadBytes = {
bytes: ArrayBuffer | undefined;
state: UseDownloadBytesState;
dispatch: UseDownloadBytesDispatcher;
};

export const useDownloadBytes = ({
reference,
}: UseDownloadBytesParams): UseDownloadBytes => {
const [state, setState] = useState<UseDownloadBytesState>("ready");
const [bytes, setBytes] = useState<ArrayBuffer | undefined>(undefined);

const dispatch: UseDownloadBytesDispatcher = async (maxDownloadSizeBytes) => {
setState("loading");
const bytes = await getBytes(reference, maxDownloadSizeBytes);
setState("done");
setBytes(bytes);
return bytes;
};

return { bytes, state, dispatch };
};