4cody
4cody

Reputation: 354

Posting to mongoDB in react with redux/redux-thunk

Mock Library Displays books (author title genre) from the database and the ability to add a book.

The data is being properly acquired from my react component.
The data is being passed in kind to my action creator and likewise is being handled correctly by the reducer.
It would seem as if my async thunk is properly set up to make the post request with axios. I am properly fetching the books already in the database with a get request.

My routes appear to be working as I am able to properly add a book and fetch all books using postman. And again, my books are displaying properly when fetched from my react component.

Where is the issue coming in? Why is my post request not reaching my database?

My actions--

export const fetchBooks = () => dispatch => {
    axios.get('/books')
        .then(res => dispatch({
            type: FETCH_BOOKS,
            payload: res.data
        })) 
}

export const addBook = ({ title, author, genre}) => dispatch => {
    dispatch(addBookStarted())
    axios
      .post('/books', {
        title, 
        author, 
        genre
      })
      .then(res => {
        dispatch(addBookSuccess(res.data))
      })
      .catch(err => {
          dispatch(addBookFailure(err.message))
      })
}


const addBookSuccess = book => ({
    type: ADD_BOOK_SUCCESS,
    payload: {
      ...book
    }
});

const addBookStarted = () => ({
    type: ADD_BOOK_STARTED
});

My reducer --

const initialState = {
    books: [],
    error: null,
    loadinng: false
}

export default function(state = initialState, action) {
    switch(action.type) {
        case FETCH_BOOKS:
            return {
                ...state,
                books: action.payload
            }

        case ADD_BOOK_STARTED:
            return {
                ...state,
                loading: true
            }

        case ADD_BOOK_SUCCESS:
            return {
                ...state,
                loading: false,
                error: null,
                books: [...state.books, action.payload]
            }

        case ADD_BOOK_FAILURE:
            return {
                ...state,
                loading: false,
                error: action.payload.error
            }

        default: 
            return state
    }
}

Error--

{ ValidationError: book validation failed: title: Path `title` is required., aut
hor: Path `author` is required., genre: Path `genre` is required.
    at ValidationError.inspect (C:\Users\Leeko\documents\repos\libapp\backend\no
de_modules\mongoose\lib\error\validation.js:59:24)
    at formatValue (internal/util/inspect.js:526:31)
    at inspect (internal/util/inspect.js:194:10)
    at Object.formatWithOptions (util.js:90:12)
    at Console.(anonymous function) (console.js:204:15)
    at Console.warn (console.js:221:31)
    at b.save.then.catch.err (C:\Users\Leeko\documents\repos\libapp\backend\serv
er.js:34:31)
    at process.internalTickCallback (internal/process/next_tick.js:77:7)
  errors:
   { title:
      { ValidatorError: Path `title` is required.
          at new ValidatorError (C:\Users\Leeko\documents\repos\libapp\backend\n
ode_modules\mongoose\lib\error\validator.js:29:11)
          at validate (C:\Users\Leeko\documents\repos\libapp\backend\node_module
s\mongoose\lib\schematype.js:926:13)
          at C:\Users\Leeko\documents\repos\libapp\backend\node_modules\mongoose
\lib\schematype.js:979:11
          at Array.forEach (<anonymous>)
          at SchemaString.SchemaType.doValidate (C:\Users\Leeko\documents\repos\
libapp\backend\node_modules\mongoose\lib\schematype.js:935:19)
          at C:\Users\Leeko\documents\repos\libapp\backend\node_modules\mongoose
\lib\document.js:1941:9
          at process.internalTickCallback (internal/process/next_tick.js:70:11)
        message: 'Path `title` is required.',
        name: 'ValidatorError',
        properties: [Object],
        kind: 'required',
        path: 'title',
        value: undefined,
        reason: undefined,
        [Symbol(mongoose:validatorError)]: true },

sever.js (route)

const mongoose    = require("mongoose");
const express     = require("express");
const bodyParser  = require("body-parser");

const db          = require('./config/db');

const Book        = require('./models/book');

const app         = express();

app.use(bodyParser.urlencoded({extended: true}));

app.route('/books')
    .get((req, res) => {
        Book.find({}).then(docs => res.json(docs))
    })
    .post((req, res) => {
        let b = new Book({
            title: req.body.title,
            author: req.body.author,
            genre: req.body.genre
        })

        b.save()
            .then(doc => console.log(doc))
            .catch(err => console.error(err))
        res.json(req.body)
    })

book model

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const BookSchema = new Schema({
    title: {
        type: String,
        // required: true,
        lowercase: true
    },
    author: {
        type: String,
        // required: true,
        lowercase: true
    },
    genre: {
        type: String,
        // required: true,
        lowercase: true
    },
    pages: {
        type: Number
    },
    available: {
        type: Boolean,
        default: true
    }
});

module.exports = Book = mongoose.model('book', BookSchema);

Upvotes: 2

Views: 1780

Answers (3)

4cody
4cody

Reputation: 354

In my server.js I was missing below:

...
app.use(bodyParser.json());
...

Upvotes: 3

Abdulla Thanseeh
Abdulla Thanseeh

Reputation: 10536

A small change in axios call

axios
      .post('/books', {
        'title':title, 
        'author':author, 
        'genre':genre
      })
      .then(res => {
        dispatch(addBookSuccess(res.data))
      })
      .catch(err => {
          dispatch(addBookFailure(err.message))
      })

post request is expecting a key-value body parser

Upvotes: 0

johnnywu
johnnywu

Reputation: 245

You may need to support the full url HOST in your axios setup, please also post error logs for context

Upvotes: 0

Related Questions