简体   繁体   中英

MERN application - NODE.JS req.body empty return

I use react redux toolkit with node.js. I have been spending hours trying to figure out why req.body is empty (with an update function). The express.json() middleware is well defined in server.js.

backend - servers.js :

    const express = require('express');
    const cors = require('cors');
    const dotenv = require('dotenv').config();
    const { errorHandler } = require('./middleware/errorMiddleware');
    const connectDB = require('./config/db');
    const port = process.env.PORT || 5000;
    
    connectDB();
    
    const app = express();
    app.use(cors());
    
    app.use(express.json());
    app.use(express.urlencoded({ extended: false })); 
    
    app.use('/api/books', require('./routes/bookRoutes'));
    
    app.use(errorHandler);
    
    app.listen(port, () => console.log(`Server started on port ${port}`));

backend - bookRoutes.js :

...
router.put('/:id', updateBook);

backend - bookController.js :

const asyncHandler = require('express-async-handler');

const updateBook = asyncHandler(async (req, res) => {
const book = await Book.findById(req.params.id);

  if (!book) {
    res.status(400);
    throw new Error('Book not found');
  }
  console.log('backend bookController req body: ', req.body);
 `//output : backend bookController req body:  {}`

  const updatedBook = await Book.findByIdAndUpdate(req.params.id, req.body, {
    new: true,
  });

  res.status(200).json(updatedBook);
});

frontend - booksSlice.js :

const initialState = {
  books: [],
  isLoading: false,
  isSuccess: false,
  isError: false,
  message: '',
};
//Update  book
export const updateBook = createAsyncThunk(
  'books/update',
  async ({ id, bookData }, thunkAPI) => {
    try {
      console.log('slice bookData : ', bookData);
      `//output: slice bookData : undefined`

      return await bookService.updateBook(id, bookData);
    } catch (error) {
      const message =
        (error.response &&
          error.response.data &&
          error.response.data.message) ||
        error.message ||
        error.toString();
      return thunkAPI.rejectWithValue(message);
    }
  }
);

frontend - bookService.js :

const API_URL = 'http://localhost:5000/api/books/';
// Update user book
const updateBook = async (bookId, bookData) => {

  console.log('axios service bookData: ', bookData);
  `//output: slice service: undefined`

  const response = await axios.put(API_URL + bookId, bookData);
 
  return response.data;
};

frontend UpdateBook.jsx

const UpdateBook = () => {
  const { id } = useParams();
  const books = useSelector((state) => state.books.books);
  const book = books.find((b) => b._id === id);

  const dispatch = useDispatch();

  const [title, setTitle] = useState(book.title);
  const [description, setDescription] = useState(book.description);
  const [author, setAuthor] = useState(book.author);

  const handleSubmitButton = (id) => {
    const bookUpdated = {
      title: title,
      description: description,
      author: author,
    };

    dispatch(updateBook({ id, bookUpdated }));

  };

  return (
    <div className="form">
      <div className="title">Update</div>
      <div className="subtitle">Let's update a book!</div>
      <div className="input-container ic1">
        <input
          id="title"
          className="input"
          type="text"
          placeholder=" "
          value={title}
          onChange={(e) => {
            setTitle(e.target.value);
          }}
        />
        <div className="cut" />
        <label htmlFor="title" className="placeholder">
          Title
        </label>
      </div>
      <div className="input-container ic2">
        <input
          id="description"
          className="input"
          type="text"
          placeholder=" "
          value={description}
          onChange={(e) => {
            setDescription(e.target.value);
          }}
        />
        <div className="cut" />
        <label htmlFor="description" className="placeholder">
          description
        </label>
      </div>
      <div className="input-container ic2">
        <input
          id="text"
          className="input"
          type="text"
          placeholder=" "
          value={author}
          onChange={(e) => {
            setAuthor(e.target.value);
          }}
        />
        <div className="cut cut-short" />
        <label htmlFor="text" className="placeholder">
          Author
        </label>
      </div>
      <button
        onClick={() => handleSubmitButton(book._id)}
        type="text"
        className="submit"
      >
        Update book!
      </button>
    </div>
  );
};

export default UpdateBook;

Note that with postman the update function works. An idea to solve my problem? Thanks.

EDIT : Could you please see my code: CodeSandbox .

Launch at port 3000 on the browser panel [Browser(:3000)]: k971xu-3000.sse.codesandbox.io/. See on the terminal and console: after update req-body is empty. Note that the create function works... An idea to solve my problem? Thanks.

I think, In backend - bookController.js, you have done something. Refer express-async-handler . And also you have not exported the controller. Therefore, in backend - bookController.js: , export your controller.

exports.updateBook = updateBook;

In backend - bookRoutes.js:

const bookController = require(<"path of your controller file">);

router.put('/:id',asyncHandler(bookController.updateBook));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM