How to wait & save result from react fetch?

Viewed 39

I am trying to build an app that uploads an image to AWS S3 using React frontend and Node / Express backend.

When the "upload" button is clicked, I want my app to

  1. Get secret upload URL from express backend
  2. Upload image to that secret upload URL.

So Far, I made to the point where react can fetch GET request to my backend & my backend can get such requests. However, for some reason the log says "Fetch failed loading GET" and is unavailable to get response from the fetch request.

I also tried using useState and useEffect, but I can't seem to resolve the issue.

React file Upload.js

import 'bootstrap/dist/css/bootstrap.css';
import React, {useState} from 'react';

function Upload() {
    const [selectedFile, setSelectedFile] = useState(null);
    
    const handleFileInput = (e) => {
        setSelectedFile(e.target.files[0]);
        console.log(e.target.files[0].name);
    }
    async function uploadFile(file)  {
        // code crashes here; fetch request does successfully reach backend, but it fails to retrieve result.
        const { url } = await fetch("/s3Url", {
            headers:{
                "accepts": "application/json"
            }
        }).then(res => res.json());
        
        console.log(url)

        await fetch(url, {
            method: "POST",
            headers: {
                "Content-Type": "multipart/form-data"
            },
            body: file
        })
        .then(res => res.json())
        
    }

    return (
        <div className="container">
            <div className="row">
                <form>
                    <h3>File upload to S3</h3>
                    <div className="form-group">
                        <input type="file" onChange={handleFileInput}/>
                    </div>
                    <div className="form-group">
                        <button className="btn btn-primary" type="submit" onClick={() => uploadFile(selectedFile)}>Upload</button>
                    </div>
                </form>
            </div>
        </div>
    )

}
export default Upload;

Backend server.js

import express from 'express';
import { generateUploadURL } from './s3.js';

const app = express();

app.use(express.json());

app.get('/s3Url', async (req, res) =>{

    // this log works
    console.log("request made")
    const url = await generateUploadURL()
    // this log works too
    console.log(url)
    res.send({url})
})

app.listen(8080, () => console.log("listening on port 8080"))

where generateUploadURL() is:

export async function generateUploadURL() {
    const rawBytes = await randomBytes(16)
    const imageName = rawBytes.toString('hex')   

    const params = ({
      Bucket: bucketName,
      Key: imageName,
      Expires: 60
    }) 
    const uploadURL = await s3.getSignedUrlPromise('putObject', params)
    return uploadURL
}

0 Answers
Related