I was creating a book library management CRUD and I am Using React v18
.
I am struggling to add data to my mongdb atlas because whenever I pass formData
to axios.post
via Redux, I'm always getting empty req.body
on the backend controller.
This however does not occur when I am using postman when adding data to my database via form-data. My login form which also using axios.post
works fine and the booklist using axios.get
also works fine, the crud for book is the only one that is not working.
This is my bookCreate.js
:
const BookCreate = () => {
const [title, setTitle] = useState('')
const [responsibility, setResponsibility] = useState('')
const [uniform_title, setUniform_title] = useState('')
const [parallel_title, setParallel_title] = useState('')
const [main_author, setMain_author] = useState('')
const [other_author, setOther_author] = useState('')
const [contributors, setContributors] = useState('')
const [corp_author, setCorp_author] = useState('')
const [placePub, setPlacePub] = useState('')
const [publisher, setPublisher] = useState('')
const [yearPub, setYearPub] = useState('')
...
const submitHandler = (e) => {
e.preventDefault();
const formData = new FormData();
formData.set('title', title);
formData.set('responsibility', responsibility);
formData.set('uniform_title', uniform_title);
formData.set('parallel_title', parallel_title);
formData.set('main_author', main_author);
formData.set('other_author', other_author);
formData.set('contributors', contributors);
formData.set('corp_author', corp_author);
formData.set('placePub', placePub);
formData.set('publisher', publisher);
formData.set('yearPub', yearPub);
dispatch(newBooks(formData))
}
return (
<Fragment>
<MetaData title={'TUP-T Online Library - Admin'} />
{/*<div className="row">*/}
<SideNavbarAdmin/>
<div></div>
<div className="dashboard-content">
<div className="dashboard-page">
<div className="dashboard-header">
<h1>Add Book</h1>
</div>
<div className="dashboard-body">
<form className="" onSubmit={submitHandler} encType='multipart/form-data'>
<div className="row g-3">
<div className="col md-6">
<div className="form-group">
<label htmlFor="title_field">Title</label>
<input
type="text"
id="title_field"
className="form-control"
name='title'
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
</div>
...
}
This is bookAction.js
:
export const newBooks = (bookData) => async (dispatch) => {
try {
dispatch({ type: NEW_BOOK_REQUEST })
const config = {
headers: {
"Content-Type": "multipart/form-data"
// "Content-Type": "application/json"
}
}
// for(var pair of bookData.entries()) {
// console.log(pair[0] ', ' pair[1]);
// }
const { data } = await axios.post('/api/v1/book/new', bookData, config)
dispatch({
type: NEW_BOOK_SUCCESS,
payload: data
})
} catch (error) {
dispatch({
type: NEW_BOOK_FAIL,
payload: error.response.data.message
})
}
}
This is bookController.js
:
exports.createBook = async (req, res, next) => {
console.log(req.body);
}
My app.js
on the backend:
const express = require("express");
const app = express();
const cookieParser = require("cookie-parser");
const errorMiddleware = require("./middlewares/errors");
app.use(express.json());
app.use(cookieParser());
app.use(errorMiddleware);
app.use(express.urlencoded({ extended: true }));
const book = require("./routes/book");
const auth = require("./routes/auth");
app.use("/api/v1", book);
app.use("/api/v1", auth);
app.use(errorMiddleware);
module.exports = app;
CodePudding user response:
FormData
send multipart/form-data
, hence the parsers you used in app.js
won't work. The common and easy way is to use multer
. First install it:
npm install --save multer
Then where you hade urlencoded
, and cookieParser
use this:
const multer = require('multer');
const upload = multer();
app.use(upload.none())
I'm using this upload.none()
because you seem to be not sending any file. If you are, you can visit the above link, mutter
will let you do that.
Also you can simplify submitHandler
since each form input
has a name
by getting ride of all those states and simply give the form
to FormData()
as parameter with e.target
:
const submitHandler = (e) => {
e.preventDefault();
const formData = new FormData(e.target);
dispatch(newBooks(formData));
};