Design+Code logo

Quick links

Suggested search

CodeSandbox link

You can find the full code for this tutorial at https://codesandbox.io/s/firebase-storage-570di.

Setup Firebase

Make sure that you have Firebase set up in your React project. If you haven't, you can set it up by reading the section Intro to Firebase of this handbook.

Enable Firebase Storage

Next, head to the Firebase Console and click on your project. To enable Firebase Storage in your project, under the Build dropdown menu, click on Storage. On the banner, click on Get started.

Screen Shot 2021-03-19 at 1.09.12 PM

Under the Rules tab, you'll need to edit your Storage rules to allow uploading pictures. We'll change it to true by default for now - remember to change them back to stronger rules before releasing your app - and click on Publish.

Screen Shot 2021-03-19 at 2.20.09 PM

Nice, you just enabled Firebase Storage!

Create your input

Now, head back to your React project and let's create our input so users can upload their photos. This input will only accept png, jpg and jpeg files.

// UploadButton.js

import React from "react";

const UploadButton = () => {
    return (
        <div>
            <input type="file" accept=".png, .jpg, .jpeg" />
        </div>
    );
};

export default UploadButton;

The result will be a default HTML button like this:

Screen Shot 2021-03-19 at 1.21.00 PM

On click of this button, a window will pop up and the user will be able to choose a picture from their computer.

Add styling

To style it up a bit, we'll create another button and hide the default HTML one. Then, we'll perform some JavaScript functions when the user will click on our custom button, to click on this default HTML button.

Create your custom button.

// MyCustomButton.js

import React from "react";
import styled from "styled-components";

const MyCustomButton = (props) => {
    return <Button onClick={props.onClick} >Upload a picture</Button>;
};

export default MyCustomButton;

const Button = styled.button`
    background: linear-gradient(91.4deg, #2fb8ff 0%, #9eecd9 100%);
    padding: 12px 0;
    width: 200px;
    border: none;
    border-radius: 30px;
    color: #fff;
    font-weight: bold;
    font-family: Segoe UI, sans-serif;
    cursor: pointer;

    :focus {
        outline: none;
    }
`;

Import MyCustomButton in UploadButton.js and call it in the return body.

// UploadButton.js

import MyCustomButton from "./MyCustomButton";
// UploadButton.js

const UploadButton = () => {
    return (
        <div>
            <MyCustomButton />
            <input type="file" accept=".png, .jpg, .jpeg" hidden />
        </div>
    );
};

Hide the default HTML button by adding the hidden attribute in the input.

// UploadButton.js

<input type="file" accept=".png, .jpg, .jpeg" hidden />

Create a useRef and add the ref to the input. Read the section useRef Hook from this handbook to learn more about it.

// UploadButton.js

import React, { useRef } from "react";
import MyCustomButton from "./MyCustomButton";

const UploadButton = () => {
    const ref = useRef(null);

    return (
        <div>
            <MyCustomButton />
            <input type="file" accept=".png, .jpg, .jpeg" hidden ref={ref} />
        </div>
    );
};

export default UploadButton;

Next, we'll create a function that will be fired when the user clicks on MyCustomButton. In this function, if the input exists, we are programmatically clicking on it at the same time the user clicks on MyCustomButton.

// UploadButton.js

const handleClick = () => {
    if (ref) {
      ref.current.click();
    }
};

Add your function onClick of MyCustomButton.

// UploadButton.js

<MyCustomButton onClick={() => handleClick()} />

On click of MyCustomButton, a window will pop up and the user will be able to select their photo from their computer.

Screen Shot 2021-03-19 at 1.41.18 PM

Call Firebase Storage

Now that our basic user flow works, we can call Firebase Storage.

Import getFirebase from firebase.js.

// UploadButton.js

import getFirebase from "./firebase"

Create a Firebase instance.

// UploadButton.js

const firebase = getFirebase()

Create a new function uploadPicture() that will call Firebase Storage and upload the user's picture.

// UploadButton.js

const handleUpload = async (event) => {
    if (!firebase) return;

    const uploadedFile = event?.target.files[0];
    if (!uploadedFile) return;

    const storage = firebase.storage();
    const storageRef = storage.ref("images");

    try {
      await storageRef.child(uploadedFile.name).put(uploadedFile);
      alert("Successfully uploaded picture!");
    } catch (error) {
      console.log("error", error);
    }
};

In the function above, we are making sure that Firebase exists. Then, we are checking if we have our uploaded file. Next, we create a Firebase storage instance and a storage reference. Finally, we try to upload our file. If the upload is successful, an alert will show. If not, the error will be printed on the console.

In your input, add the onChange attribute and call the handleUpload function.

// UploadButton.js

<input
		type="file"
		ref={ref}
		accept=".png, .jpg, .jpeg"
		hidden
		onChange={handleUpload}
/>

Test everything!

Now it's time to test everything! Click on the Upload a picture button, select your image and upload it! If you get the following alert, congratulations! Your file has been uploaded to Firebase Storage.

Screen Shot 2021-03-19 at 2.28.01 PM

You can also head over to Firebase Console and see if your file has been successfully uploaded under the images folder.

Screen Shot 2021-03-19 at 2.29.07 PM

Final code

Here is the final code of the UploadButton file:

// UploadButton.js

import React, { useRef } from "react";

import getFirebase from "./firebase";
import MyCustomButton from "./MyCustomButton";

const UploadButton = () => {
    const firebase = getFirebase();
    const ref = useRef(undefined);

    const handleClick = () => {
        if (ref) {
            return ref.current?.click();
        }
    };

    const handleUpload = async (event) => {
        if (!firebase) return;

        const uploadedFile = event?.target.files[0];
        if (!uploadedFile) return;

        const storage = firebase.storage();
        const storageRef = storage.ref("images");

        try {
            await storageRef.child(uploadedFile.name).put(uploadedFile);
            alert("Successfully uploaded picture!");
        } catch (error) {
            console.log("error", error);
        }
    };

    return (
        <div>
          <MyCustomButton onClick={() => handleClick()} />
          <input
            type="file"
            ref={ref}
            accept=".png, .jpg, .jpeg"
            hidden
            onChange={handleUpload}
          />
        </div>
    );
};

export default UploadButton;

Learn with videos and source files. Available to Pro subscribers only.

Purchase includes access to 50+ courses, 320+ premium tutorials, 300+ hours of videos, source files and certificates.

BACK TO

Firestore

READ NEXT

Serverless Email Sending

Templates and source code

Download source files

Download the videos and assets to refer and learn offline without interuption.

check

Design template

check

Source code for all sections

check

Video files, ePub and subtitles

Browse all downloads