Search code examples
node.jsreactjsmongodbrelational-database

How do you insert multiple objects into one mongoDB post request


I have built a workout tracker app, that allows you to create a session and in that session have multiple movements. I had my app connected to a airtable API, and have just started learning mongoDB and have transitioned over to that database. At the moment i am able to send a session, but it only logs one movement, not all that were sent.

Below is the code for my dynamic state for my session form.

const [formData, setFormData] = useState([
    {
      movement: '',
      weight: '',
      rpe: '',
      reps: '',
      sets: '',
      notes: '',
      session: [
        ""
      ]
    }
  ])

const handleChange = (e, index) => {
    const { name, value } = e.target;
    const form = [...formData];
    form[index][name] = value;
    form[index].session[0] = sessionId;
    setFormData(form);
  };

  const handleAddInput = () => {
    setFormData([...formData,
      {
        movement: '',
        weight: '',
        rpe: '',
        reps: '',
        sets: '',
        notes: '',
        session: [
          ''
        ]
      }
    ]);
  };

Maping over state and inluding the movement in my body data for my API call i am able to get data to my database but it is only sending one. I understand why its only sending one. I just cant figure out any other way to include the data in the body for the API call. I have plundered google and cant find anything.

Below is my HandleSubmit for my form including the API call.

const handleSessionSubmit = async (e) => {
    e.preventDefault()
    formData.forEach(async movement => {
      const sessionData = {
        sessionName,
        date,
        movements: [{ ...movement }]
      }
      const sessionPost = await api.post('/sessions', sessionData )
      console.log(sessionPost);
      
    })
    
    props.setToggle(prevToggle => !prevToggle)
      navigate('/')
    // }
  }

Below is the Database Schema

import mongoose from 'mongoose'

const Schema = mongoose.Schema

const Movements = new Schema( 
  {
    movement: { type: String },
    weight: { type: String },
    reps: { type: String },
    rpe: { type: String },
    sets: { type: String },
    notes: { type: String },
  }
)

const Session = new Schema(
  {
    sessionName: { type: String },
    date: { type: String },
    movements: [ Movements ]
  },
  { timestamps: true}
)

export default mongoose.model('sessions', Session)

If you want to check out how it works below is the Website URL Website: https://pain-workout.netlify.app/

Thanks in advance!


Solution

  • The behavior you communicate the server is wrong, you shouldn't hit the server multiple times for the same request within a short time, instead of this you can send the whole payload for all movements one time. As I see, you put the post request inside a forEach method which will surely send to the api for each item, instead of this you can map these formData items inside one array and then send them in the post request outside the loop. here is an example:

    Frontend Side

    const handleSessionSubmit = async (e) => {
        e.preventDefault()
        const movements = formData.map(movement => movement);
        const sessionData = {sessionName, date, movements};
        const sessionPost = await api.post('/sessions', sessionData )
        props.setToggle(prevToggle => !prevToggle)
          navigate('/')
        // }
      }
    

    Backend Side

    app.post('/sessions', async (req, res, next) => {
      try {
         const sessionData = req.body;
         const session = new Session(sessionData);
         await session.save();
      } catch(err) {
        throw err;
      }
    });