I'm trying to send data to my database using a react form and it's not working as it should. When I click the button, the function handleSubmit
is called but it gets an error for some reason.
This is the error I see in the console when I click the button:
Here is the code for the react form:
import { useState } from "react";
const ProjectAdminForm = () => {
const [sdg_desc, setSDGDesc] = useState('')
const [sdg_num, setSDGNum] = 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 [error, setError] = useState(null)
const handleSubmit = async (e) => {
e.preventDefault() // Prevents refresh of page from happening
console.log('button clicked')
const project = {sdg_desc, sdg_num, goal, orginization, source, location, published, website_url, assignment_type, sharepoint_link, statement}
// 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
setSDGDesc('')
setSDGNum('')
setGoal('')
setOrginization('')
setSource('')
setLocation('')
setPublished('')
setWebsiteURL('')
setAssignmentType('')
setSharepointLink('')
setStatement('')
setError(null)
console.log('new project added', json)
}
}
return (
<form className="create" onSubmit={handleSubmit}>
<h3>Add a New Project</h3>
<label>SDG Name:</label>
<input
type="text"
onChange={(e) => setSDGDesc(e.target.value)}
value={sdg_desc}
/>
<label>SDG Num:</label>
<input
type="text"
onChange={(e) => setSDGNum(e.target.value)}
value={sdg_num}
/>
<label>Goal:</label>
<input
type="text"
onChange={(e) => setGoal(e.target.value)}
value={goal}
/>
<label>Orginization:</label>
<input
type="text"
onChange={(e) => setOrginization(e.target.value)}
value={orginization}
/>
<label>Source:</label>
<input
type="text"
onChange={(e) => setSource(e.target.value)}
value={source}
/>
<label>Location:</label>
<input
type="text"
onChange={(e) => setLocation(e.target.value)}
value={location}
/>
<label>Published:</label>
<input
type="text"
onChange={(e) => setPublished(e.target.value)}
value={published}
/>
<label>Website URL:</label>
<input
type="text"
onChange={(e) => setWebsiteURL(e.target.value)}
value={website_url}
/>
<label>Assignment Type:</label>
<input
type="text"
onChange={(e) => setAssignmentType(e.target.value)}
value={assignment_type}
/>
<label>Sharepoint Link:</label>
<input
type="text"
onChange={(e) => setSharepointLink(e.target.value)}
value={sharepoint_link}
/>
<label>Statement:</label>
<input
type="text"
onChange={(e) => setStatement(e.target.value)}
value={statement}
/>
<button>Add Project</button>
{error && <div className="error">{error}</div>}
</form>
)
}
export default ProjectAdminForm
Here is the code of the backend api it points too:
// create new project
const createProject = async (req, res) => {
// adding in a new project
const {sdg_desc, sdg_num, goal, orginization, source, location, published, website_url, assignment_type, sharepoint_link, statement} = req.body
try {
const project = await Project.create({sdg_desc, sdg_num, goal, orginization, source, location, published, website_url, assignment_type, sharepoint_link, statement})
res.status(200).json(project)
} catch (error) {
res.status(400).json({error: error.message})
}
}
Could someone tell me why when I click the "Add Project" button I get this error?
CodePudding user response:
There are multiple problems. I am gonna assume you are using MongoDB and mongoose, so your code for backend should look like this.
const createProject = async (req, res) => {
const {sdg_desc, sdg_num, goal, orginization, source, location, published, website_url, assignment_type, sharepoint_link, statement} = req.body
const newProject = new Project{(
sdg_desc: sdg_desc,
sdg_num : sdg_num,
goal : goal,
orginization : orginization,
source : source,
location : location,
published : published,
website_url : website_url,
assignment_type : assignment_type,
sharepoint_link : sharepoint_link,
statement : statement
)};
try {
await newProject.save();
} catch (error) {
res.status(500).json({error: error.message})
}
res.status(201).json({project: newProject});
}
And on the frontend when you are using the fetch API, you need to specify full link to the backend, so it should look like this
const response = await fetch('http://localhost:8000/api/projects', {
method: 'POST',
body: JSON.stringify(project),
headers: {
'Content-Type': 'application/json'
}
})
Also make sure that the data you are sending to the backend have the same name on the frontend
CodePudding user response:
Looks like the problem is coming from your backend, are you using any middlewares, validators like Joi ?
CodePudding user response:
<button>Add Project</button>
Should be
<button onClick={handleSubmit}>Add Project</button>
or
<button onClick={()=>handleSubmit()}>Add Project</button>
You don’t call your function for some reason
I think you can work it out with form like that (but honestly I haven’t seen even single time somebody does it like that in react) but then you have to give something like:
<button type=“submit”>…
So also I would refactor a bit your bunch of setState:
const [state,setState] = useState({});
const handleInputChange = (e) => setState({…state, [e.target.name]:e.target.value});
On inputs:
<input name=“project” onChange={handleInputChange}>…</input>
This will give much more flexible state with less code
You should add console.log(req.body) This would point to source of error