Skip to content

Commit 1b5d962

Browse files
committed
[storage] Add useUploadFile hook
1 parent 8746c23 commit 1b5d962

File tree

4 files changed

+123
-6
lines changed

4 files changed

+123
-6
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-firebase-hooks",
3-
"version": "5.0.0-alpha.5",
3+
"version": "5.0.0-alpha.7",
44
"description": "React Hooks for Firebase",
55
"author": "CS Frequency Limited (https://csfrequency.com)",
66
"license": "Apache-2.0",

storage/README.md

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { useDownloadURL } from 'react-firebase-hooks/storage';
1515
List of Cloud Storage hooks:
1616

1717
- [useDownloadURL](#usedownloadurl)
18+
- [useUploadFile](#useuploadfile)
1819

1920
### useDownloadURL
2021

@@ -32,20 +33,18 @@ Returns:
3233

3334
- `downloadUrl`: A `string` download URL, or `undefined` if no storage reference is supplied
3435
- `loading`: A `boolean` to indicate whether the the download URL is still being loaded
35-
- `error`: Any `storage.StorageError` returned by Firebase when trying to load the user, or `undefined` if there is no error
36+
- `error`: Any `storage.StorageError` returned by Firebase when trying to load the URL, or `undefined` if there is no error
3637

3738
#### Full example
3839

3940
```js
40-
import { ref, getStorage } from 'firebase/storage';
41+
import { getStorage, storageRef } from 'firebase/storage';
4142
import { useDownloadURL } from 'react-firebase-hooks/storage';
4243

4344
const storage = getStorage(firebaseApp);
4445

4546
const DownloadURL = () => {
46-
const [value, loading, error] = useDownloadURL(
47-
ref(storage, 'path/to/file')
48-
);
47+
const [value, loading, error] = useDownloadURL(ref(storage, 'path/to/file'));
4948

5049
return (
5150
<div>
@@ -62,3 +61,61 @@ const DownloadURL = () => {
6261
);
6362
};
6463
```
64+
65+
### useUploadFile
66+
67+
```js
68+
const [uploadFile, uploading, snapshot, error] = useUploadFile();
69+
```
70+
71+
Upload a file to Firebase storage.
72+
73+
The `useUploadFile` hook returns the following:
74+
75+
- `uploadFile(ref, file, metadata)`: A function that can be called to upload a file, with attached metadata, to the storage reference supplied
76+
- `uploading`: A `boolean` to indicate whether the the file is currently being uploaded
77+
- `snapshot`: A `storage.UploadTaskSnapshot` to provide more detailed information about the upload
78+
- `error`: Any `storage.StorageError` returned by Firebase when trying to upload the file, or `undefined` if there is no error
79+
80+
#### Full example
81+
82+
```js
83+
import { getStorage, storageRef } from 'firebase/storage';
84+
import { useUploadFile } from 'react-firebase-hooks/storage';
85+
86+
const storage = getStorage(firebaseApp);
87+
88+
const UploadFile = () => {
89+
const [uploadFile, uploading, snapshot, error] = useUploadFile();
90+
const ref = storageRef(storage, 'file.jpg');
91+
const [selectedFile, setSelectedFile] = useState<File>();
92+
93+
const upload = async () => {
94+
if (selectedFile) {
95+
const result = await uploadFile(ref, selectedFile, {
96+
contentType: 'image/jpeg'
97+
});
98+
alert(`Result: ${JSON.stringify(result)}`);
99+
}
100+
}
101+
102+
return (
103+
<div>
104+
<p>
105+
{error && <strong>Error: {error.message}</strong>}
106+
{uploading && <span>Uploading file...</span>}
107+
{snapshot && <span>Snapshot: {JSON.stringify(snapshot)}</span>}
108+
{selectedFile && <span>Selected file: {selectedFile.name}</span>}
109+
<input
110+
type="file"
111+
onChange={(e) => {
112+
const file = e.target.files ? e.target.files[0] : undefined;
113+
setSelectedFile(file);
114+
}}
115+
/>
116+
<button onClick={upload}>Upload file</button>
117+
</p>
118+
</div>
119+
)
120+
}
121+
```

storage/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export { default as useDownloadURL, DownloadURLHook } from './useDownloadURL';
2+
export { default as useUploadFile, UploadFileHook } from './useUploadFile';

storage/useUploadFile.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import {
2+
StorageError,
3+
StorageReference,
4+
uploadBytesResumable,
5+
UploadMetadata,
6+
UploadResult,
7+
UploadTaskSnapshot,
8+
} from 'firebase/storage';
9+
import { useMemo, useState } from 'react';
10+
11+
export type UploadFileHook = [
12+
(
13+
storageRef: StorageReference,
14+
data: Blob | Uint8Array | ArrayBuffer,
15+
metadata?: UploadMetadata | undefined
16+
) => Promise<UploadResult | undefined>,
17+
boolean,
18+
UploadTaskSnapshot | undefined,
19+
StorageError | undefined
20+
];
21+
22+
export default (): UploadFileHook => {
23+
const [error, setError] = useState<StorageError>();
24+
const [uploading, setUploading] = useState<boolean>(false);
25+
const [snapshot, setSnapshot] = useState<UploadTaskSnapshot>();
26+
27+
const uploadFile = async (
28+
storageRef: StorageReference,
29+
data: Blob | Uint8Array | ArrayBuffer,
30+
metadata?: UploadMetadata | undefined
31+
): Promise<UploadResult | undefined> => {
32+
return new Promise((resolve, reject) => {
33+
setUploading(true);
34+
const uploadTask = uploadBytesResumable(storageRef, data, metadata);
35+
uploadTask.on(
36+
'state_changed',
37+
(snapshot) => {
38+
setSnapshot(snapshot);
39+
},
40+
(error) => {
41+
setUploading(false);
42+
setError(error);
43+
resolve(undefined);
44+
},
45+
() => {
46+
setUploading(false);
47+
setSnapshot(undefined);
48+
resolve({
49+
metadata: uploadTask.snapshot.metadata,
50+
ref: uploadTask.snapshot.ref,
51+
});
52+
}
53+
);
54+
});
55+
};
56+
57+
const resArray: UploadFileHook = [uploadFile, uploading, snapshot, error];
58+
return useMemo<UploadFileHook>(() => resArray, resArray);
59+
};

0 commit comments

Comments
 (0)