1

I'm trying to add a form in which users can add text and images which is then going to be stored on the mongodb database. As of right now, I'm trying to add a section in the form where users can add images. I'm trying to figure out a way to store an image that the user uploads and send it to the backend (I'm using MERN stack).

This is my code that deals with the form, in terms of getting user input and sending it to the backend:

import { useState } from "react";
import { adminSDGOptions } from "./AdminCategoryLists";
import { adminAssingmentOptions } from "./AdminCategoryLists";
import { keywordsOptions } from "../FilterComponents/CategoryArrays/KeywordsOptions";
import Multiselect from "multiselect-react-dropdown"
import Select from 'react-select';

const ProjectAdminForm = () => {
    // Adding basic info
    const [sdg, setSDG] = useState('')
    const [goal, setGoal] = useState('')
    const [orginization, setOrginization] = useState('')
    const [source, setSource] = useState('')
    const [location, setLocation] = useState('')
    const [published, setPublished] = useState('')
    const [website_url, setWebsiteURL] = useState('')
    const [assignment_type, setAssignmentType] = useState('')
    const [sharepoint_link, setSharepointLink] = useState('')
    const [statement, setStatement] = useState('')
    const [preview_img, setPreviewImg] = useState([])
    const [error, setError] = useState(null)

    // Adding keywords
    const [keywords, setKeywords] = useState([]);


    const handleSubmit = async (e) => {
        e.preventDefault() // Prevents refresh of page from happening
        console.log('button clicked')

        const project = {sdg, goal, orginization, source, location, published, website_url, assignment_type, keywords, sharepoint_link, statement, preview_img}
        console.log(project)
            
        // Sending form response to backend
        const response = await fetch('/api/projects', {
            method: 'POST',
            body: JSON.stringify(project),
            headers: {
                'Content-Type': 'application/json'
            }
        })
        const json = await response.json
        

        // Checking for error
        if (!response.ok) {
            setError(json.error)
        }
        if (response.ok) {
            // Reset form inputs back to empty string
            setSDG('')
            setGoal('')
            setOrginization('')
            setSource('')
            setLocation('')
            setPublished('')
            setWebsiteURL('')
            setAssignmentType('')
            setKeywords([])
            setSharepointLink('')
            setStatement('')
            
            setError(null)
            alert('Project added!')
            console.log('new project added', json)
        }
    }

    return (
        <form className="create project-form" onSubmit={handleSubmit}>
            <h2 style={{"textAlign": "center"}}>Add a New Project</h2>

            <hr></hr>

            <label>Sustainable Development Goal:</label>
            <Select
                className="basic-single"
                classNamePrefix="select"
                placeholder="Select"
                name="color"
                options={adminSDGOptions}
                onChange={(selection) => setSDG(selection.value)}
                required
            />

            <label>Description:</label>
            <input 
                type="text"
                onChange={(e) => setGoal(e.target.value)}
                value={goal}
                required
            />

            <label>OPTIONAL - Organization:</label>
            <input 
                type="text"
                onChange={(e) => setOrginization(e.target.value)}
                value={orginization}
            />

            <label>OPTIONAL - Source:</label>
            <input 
                type="text"
                onChange={(e) => setSource(e.target.value)}
                value={source}
            />

            <label>OPTIONAL - Location:</label>
            <input 
                type="text"
                onChange={(e) => setLocation(e.target.value)}
                value={location}
            />

            <label>Published (YEAR ONLY):</label>
            <input 
                type="text"
                onChange={(e) => setPublished(e.target.value)}
                value={published}
                required
            />

            <label>OPTIONAL - Website URL:</label>
            <input 
                type="text"
                onChange={(e) => setWebsiteURL(e.target.value)}
                value={website_url}
            />

            <label>Assignment Type:</label>
            <Select
                className="basic-single"
                classNamePrefix="select"
                placeholder="Select"
                name="color"
                options={adminAssingmentOptions}
                onChange={(selection) => setAssignmentType(selection.value)}
                required
            />

            <hr></hr>

            <label>Enter Keyword(s):</label>
            <Multiselect
                className="multiselect-admin"
                isObject={false}
                onRemove={(selection) => setKeywords(selection)}
                onSelect={(selection) => setKeywords(selection)}
                options={keywordsOptions}
                required
            />

            <hr></hr>

            <label>OPTIONAL - Statement (ONLY Assessment Ideas and Discussion Topics):</label>
            <input 
                type="text"
                onChange={(e) => setStatement(e.target.value)}
                value={statement}
            />

            <label>OPTIONAL - Qualtrics Link (ONLY Mini Case Study):</label>
            <input 
                type="text"
                onChange={(e) => setSharepointLink(e.target.value)}
                value={sharepoint_link}
            />
            
            // THIS IS THE SECTION I'M TRYING TO ADD AND AM NOT SURE HOW TO GO ABOUT DOING SO
            <label>OPTIONAL - Preview image:</label>
            <input
                type="file"
                name="preview_img"
                accept="image/*"
                onChange={(e) => setPreviewImg(e.target.value)}
            />
            
            <div className="add-proj">
                <button>Add Project</button>
            </div>
            
            {error && <div className="error">{error}</div>}
        </form>
    )
}

export default ProjectAdminForm

The main thing I'm trying to get working is the preview_img stuff, I'm able to ask the user for an image through <input/> but then when I store itin my useState which is set up like this const [preview_img, setPreviewImg] = useState([]), it doesn't save the actual image, rather a string which looks like this:

preview_img: "C:\\fakepath\\banner2 (2).jpg"

I'm not sure how to save the actual image and then send it to the backend in my handleSubmit function since it appears I can't just include the state name (preview_img) in the object I'm sending to the backend.

Soccerball123
  • 741
  • 5
  • 17
  • Does this answer your question? [React, image is not uploading, getting filename is not defined error](https://stackoverflow.com/questions/71136807/react-image-is-not-uploading-getting-filename-is-not-defined-error) – Youssouf Oumar Aug 23 '22 at 19:48

1 Answers1

0

You can reach and upload the image in onChange function. If you want to use it by accessing local url, you can create and store its local url in a state.

const [imageURL,setImageURL] = useState()

onChange={(event) => {
    let file = event.target.files[0]
    yourUploadFunction(file, url)
    setImageURL(URL.createObjectURL(file))
}}
ilketorun
  • 324
  • 3
  • 14
  • Ultimately I'm going to need to send the image to the backend and then to a database, so is there a way to actually save the image in terms of like hashing or something and then send that to the backend? – Soccerball123 Aug 23 '22 at 15:41
  • you can use its url to reach the image. See this post: https://stackoverflow.com/questions/73454020/how-to-upload-local-video-file-to-google-cloud – ilketorun Aug 23 '22 at 15:45
  • Would that still work even if I publish the web app and it's not hosted on my localhost anymore? – Soccerball123 Aug 23 '22 at 16:06
  • Well, we are using kind of similar structure. It works. – ilketorun Aug 23 '22 at 16:11