-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
useUploadFileResumable
hook (#51)
* init useUploadFileResumable hook * test and impl initially, useUploadFileResumable hook > should have ready state * impl useUploadFileResumable * init docs for useUploadFileResumable * explain useUploadFile performance and ui * write docs for useUploadFileResumable
- Loading branch information
Showing
7 changed files
with
121 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
--- | ||
tags: | ||
- hook | ||
--- | ||
|
||
# `useUploadFileResumable` Hook | ||
|
||
`useUploadFileResumable` hook is used to upload a file to Firebase Storage. It listens to the progress, thus, it is good for progressbar-like indicators but not performant at all since it causes frequent rerendering due to constant state changes. A very simple example would be: | ||
|
||
```typescript | ||
const reference = ref(storage, "path/to/remote/file.png"); | ||
const { dispatch } = useUploadFileResumable({ reference }); | ||
const result = await dispatch(file); | ||
``` | ||
|
||
!!! warning | ||
`useUploadFileResumable` is lazy by default and will not do anything until you use `dispatch` function. | ||
|
||
You can listen to its state shown in example below: | ||
|
||
```typescript | ||
const { state } = useUploadFileResumable({ reference }); | ||
await dispatch(); | ||
// `state` is "ready" | [number, number] | "done" | ||
|
||
if (typeof state === "array") { | ||
const bytesTransferred = state[0]; | ||
const bytesTotal = state[1]; | ||
} | ||
``` | ||
|
||
`dispatch` method will return an instance of [`UploadResult`][UploadResultRefDoc]. | ||
|
||
## Input Parameters | ||
|
||
Input parameters for `useUploadFileResumable` hook is as follows: | ||
|
||
| Name | Type | Description | Required | Default Value | | ||
|---|---|---|---|---| | ||
| `reference` | [`firebase/storage/StorageReference`][StorageReferenceRefDoc] | Reference to a file in Storage. | ✅ | - | | ||
|
||
## Return Type | ||
|
||
`useUploadFileResumable` hook returns an object with properties as below: | ||
|
||
| Name | Type | Description | | ||
|---|---|---| | ||
| `state` | `"ready" | [number, number] | "done"` | The state of the upload process. | | ||
| `dispatch` | `(file: File | Blob | Buffer, metadata?: UploadMetadata) => Promise<UploadResult>` | A callback to start upload process. | | ||
|
||
[StorageReferenceRefDoc]: https://firebase.google.com/docs/reference/js/storage.storagereference | ||
[UploadResultRefDoc]: https://firebase.google.com/docs/reference/js/storage.uploadresult |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,3 +4,5 @@ | |
// https://opensource.org/licenses/MIT | ||
|
||
export * from "./useUploadFile"; | ||
|
||
export * from "./useUploadFileResumable"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// 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 { useUploadFileResumable } from "."; | ||
import { storage } from "../firebase"; | ||
|
||
const reference = ref(storage, "files/README.md"); | ||
|
||
describe("initially, useUploadFileResumable hook", () => { | ||
it("should have ready state", async () => { | ||
const { result } = renderHook(() => useUploadFileResumable({ reference })); | ||
const { state } = result.current; | ||
expect(state).toBe("ready"); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Copyright (c) 2024 Eray Erdin | ||
// | ||
// This software is released under the MIT License. | ||
// https://opensource.org/licenses/MIT | ||
|
||
import { | ||
StorageReference, | ||
UploadMetadata, | ||
UploadResult, | ||
uploadBytesResumable, | ||
} from "firebase/storage"; | ||
import { useState } from "react"; | ||
|
||
type UseUploadFileResumableParams = { | ||
reference: StorageReference; | ||
}; | ||
|
||
type UseUploadFileResumableState = "ready" | [number, number] | "done"; | ||
type UseUploadFileResumableDispatcher = ( | ||
file: Buffer | File | Blob, | ||
metadata?: UploadMetadata, | ||
) => Promise<UploadResult>; | ||
type UseUploadFileResumable = { | ||
state: UseUploadFileResumableState; | ||
dispatch: UseUploadFileResumableDispatcher; | ||
}; | ||
|
||
export const useUploadFileResumable = ({ | ||
reference, | ||
}: UseUploadFileResumableParams): UseUploadFileResumable => { | ||
const [state, setState] = useState<UseUploadFileResumableState>("ready"); | ||
|
||
const dispatch: UseUploadFileResumableDispatcher = async (file, metadata) => { | ||
const task = uploadBytesResumable(reference, file, metadata); | ||
task.on("state_changed", (snapshot) => { | ||
setState([snapshot.bytesTransferred, snapshot.totalBytes]); | ||
}); | ||
const result = await task; | ||
setState("done"); | ||
return result; | ||
}; | ||
|
||
return { state, dispatch }; | ||
}; |