I'm trying to write a file into cloud storage from within my React app. I created a new React app using the create-react-app tool. I believe I have followed the correct instructions to get a storage reference, with code like this: this.storage = firebase.storage();
. But, no matter how I configure firebase and no matter what I import, I see this error: TypeError: _this.firebase.storage() is not a function.
.
I tried importing @firebase/storage
(commented out here) but this results in an error, and the NPM page for that module suggests this is not something a user should ever load directly.
I believe I added the proper firebase libraries. I can use firestore and the legacy database (I removed the code to do it, but it works if I use something like this.firestore = this.firebase.firestore();
). But, storage is unresolved.
I'm a little unclear as to whether I should be using client libraries for cloud storage (I believe that is exactly the same thing as "storage" for Firebase). But, all the examples seem to be for accessing storage from a NodeJS app, and I want to write the file from within my browser context as client-side JavaScript.
My package.json looks like this:
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"@firebase/app": "^0.3.2",
"@firebase/auth": "^0.5.2",
"@firebase/firestore": "^0.5.6",
"@material-ui/core": "^1.3.1",
"@material-ui/icons": "^1.1.0",
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",
"react": "^16.4.1",
"react-dom": "^16.4.1"
},
"scripts": {
"start": "PORT=3009 react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
My index.js
looks like this:
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import firebase from '@firebase/app';
import '@firebase/firestore';
import '@firebase/auth';
//import '@firebase/storage';
var config = {
apiKey: "ABCDEFG",
authDomain: "abcdefg.firebaseapp",
databaseURL: "",
projectId: "abcdefg",
storageBucket: "abcdefg.appspot",
messagingSenderId: "12345"
};
firebase.initializeApp(config);
class Index extends Component {
constructor(props) {
super(props);
this.state = {};
this.firebase = firebase;
this.firestore = this.firebase.firestore(); // This works fine.
this.storage = this.firebase.storage(); // This fails
console.log( "Got storage ref" );
}
render() {
return (
<div>
Hello
</div>
)
}
}
ReactDOM.render(
<Index/>,
document.getElementById('react-container')
);
The firebase config is copied from the Firebase console (but changed here).
I'm trying to write a file into cloud storage from within my React app. I created a new React app using the create-react-app tool. I believe I have followed the correct instructions to get a storage reference, with code like this: this.storage = firebase.storage();
. But, no matter how I configure firebase and no matter what I import, I see this error: TypeError: _this.firebase.storage() is not a function.
.
I tried importing @firebase/storage
(commented out here) but this results in an error, and the NPM page for that module suggests this is not something a user should ever load directly.
I believe I added the proper firebase libraries. I can use firestore and the legacy database (I removed the code to do it, but it works if I use something like this.firestore = this.firebase.firestore();
). But, storage is unresolved.
I'm a little unclear as to whether I should be using client libraries for cloud storage (I believe that is exactly the same thing as "storage" for Firebase). But, all the examples seem to be for accessing storage from a NodeJS app, and I want to write the file from within my browser context as client-side JavaScript.
My package.json looks like this:
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"@firebase/app": "^0.3.2",
"@firebase/auth": "^0.5.2",
"@firebase/firestore": "^0.5.6",
"@material-ui/core": "^1.3.1",
"@material-ui/icons": "^1.1.0",
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",
"react": "^16.4.1",
"react-dom": "^16.4.1"
},
"scripts": {
"start": "PORT=3009 react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
My index.js
looks like this:
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import firebase from '@firebase/app';
import '@firebase/firestore';
import '@firebase/auth';
//import '@firebase/storage';
var config = {
apiKey: "ABCDEFG",
authDomain: "abcdefg.firebaseapp.com",
databaseURL: "https://abcdefg.firebaseio.com",
projectId: "abcdefg",
storageBucket: "abcdefg.appspot.com",
messagingSenderId: "12345"
};
firebase.initializeApp(config);
class Index extends Component {
constructor(props) {
super(props);
this.state = {};
this.firebase = firebase;
this.firestore = this.firebase.firestore(); // This works fine.
this.storage = this.firebase.storage(); // This fails
console.log( "Got storage ref" );
}
render() {
return (
<div>
Hello
</div>
)
}
}
ReactDOM.render(
<Index/>,
document.getElementById('react-container')
);
The firebase config is copied from the Firebase console (but changed here).
Share Improve this question asked Jul 7, 2018 at 5:57 xrdxrd 4,0697 gold badges33 silver badges41 bronze badges3 Answers
Reset to default 10This works: $ npm i @firebase/storage --save
.
This currently results in "@firebase/storage": "^0.2.3"
inside package.json
.
If I have that, I can use code like this in my firebaseConfig.js
file to setup storage inside firebase:
import firebase from '@firebase/app';
import '@firebase/firestore';
import '@firebase/auth';
import '@firebase/storage';
Then code like this works:
const storage = firebase.storage();
const files = [ 'image1.png', 'image2.png' ];
files.map( filename => {
storage
.ref( `/covers/${filename}` )
.getDownloadURL()
.then( url => {
console.log( "Got download url: ", url );
});
});
You're not importing firebase-storage, so that means the service won't be available in your code.
"@firebase/storage": "^5.1.0",
The rest of your code looks fine, once you add this dependency.
First you need to add firebase
to your app
npm i firebase
or
yarn add firebase
Please check in your package.json
if the version of your firebase is >9.0
because I will talk about that only.
By this time I also expect you to already have registered your app in Firebase console and have got your credentials. If not so then do that first.
In /src/
folder of your project add a new file firebase.js
// src/firebase.js
import firebase from "firebase/compat/app";
import { FIREBASE_CONFIG } from "./constants/firebase";
import "firebase/compat/storage";
firebase.initializeApp(FIREBASE_CONFIG);
export const storage = firebase.storage();
export default firebase;
In place of the FIREBASE_CONFIG
place your credentials object.
Next make a new file to create a function
// src/services/firebase/firebase.service.js
import React, { useState } from "react";
import { storage } from "../../firebase";
export class FirebaseService {
uploadToFirebaseStorage(files = []) {
let urls = [];
if (files.length > 0) {
files.map((file) => {
const uploadTask = storage.ref(`/img/${file.name}`).put(file);
uploadTask.on(
"state_changed",
(snapshot) => {
const progress = Math.round(
(snapshot.bytesTransferred / snapshot.totalBytes) * 100
);
},
(error) => {
console.log(error);
},
() => {
storage
.ref("img")
.child(file.name)
.getDownloadURL()
.then((newUrl) => {
urls.push(newUrl);
console.log(newUrl);
});
}
);
});
return urls;
}
}
}
If you only want the function only copy paste the function from here.
Now this files
prop will accept an array of files / images and it will give back urls
which is an array of links where you can access the uploaded files.
Here the storage
is the same as which I exported from earlier.
A sample to call this function I have also showed here.
src/App.js
import React, { useState } from "react";
import { FirebaseService } from "./services/firebase/firebase.service";
export default function App() {
const [files, setFiles] = useState([]);
const fbs = new FirebaseService();
return (
<React.Fragment>
<input
type={"file"}
onChange={(e) => {
let temp = files;
temp.push(e.target.files[0]);
setFiles(temp);
}}
></input>
<button
onClick={() => {
console.log("Hi");
fbs.uploadToFirebaseStorage(files);
}}
>
Upload
</button>
</React.Fragment>
);
}