How to send data from React frontend to Express backend for Airtable database insertion

I’m struggling with transferring data from my React app to my Express server and then inserting it into Airtable. The issue seems to be with how I’m handling the JSON data.

My React component sends data like this:

handleFormSubmission() {
  const recordData = {
    name: 'hello',
  }
  fetch('/api/create-record',{
    method: 'POST',
    body: JSON.stringify(recordData),
    headers: {"Content-Type": "application/json"}
  })
}

On the Express side, I have:

app.post('/api/create-record', jsonParser, async (req, res) => { 
    const recordInfo = JSON.stringify(req.body);   
    await console.log(recordInfo); 
    base.create(recordInfo, function(err, result) {  
        if (err) {console.log(err); res.json(err)} else {console.log(result), res.json('Created successfully!')}
    });   
})

The weird thing is that when I hardcode the object directly like base.create({"name":"hello"}) instead of using the recordInfo variable, it works perfectly. But when I pass the variable from the request body, Airtable throws errors.

I think there might be something wrong with my JSON parsing or data formatting. Any ideas what could be causing this problem?

Exactly what sophiac said - you’re turning your object into a string when Airtable needs an object.

I’ve made this same mistake working with APIs. The jsonParser middleware already converts your JSON string into a JavaScript object, so req.body is ready to go.

When you do JSON.stringify(req.body), here’s what happens:

// req.body is: {name: 'hello'}
// JSON.stringify(req.body) becomes: '{"name":"hello"}'

Airtable gets that string and doesn’t know what to do with it. It wants {name: 'hello'}, not a string version.

Just pass req.body directly:

app.post('/api/create-record', jsonParser, async (req, res) => { 
    console.log(req.body); // This shows you the actual object
    base.create(req.body, function(err, result) {  
        if (err) {console.log(err); res.json(err)} else {console.log(result), res.json('Created successfully!')}
    });   
})

Also, you don’t need await with console.log - it’s not async.

both answers are spot on! i ran into this same issue last month and spent a ton of time on it. the problem is that extra JSON.stringify() call - airtable needs a plain object, not a stringified version. hardcoding works since you’re using the correct format, while stringify messes up req.body. just pass req.body directly and you’ll be good!

You’re double-stringifying your data. When you use JSON.stringify(req.body) in your Express route, you’re converting the already parsed object back into a string. That means you’re passing a string to base.create() instead of an object. Airtable expects an object with actual field values, not a JSON string. Since you’re already using jsonParser middleware (assuming it’s express.json()), req.body is already a proper JavaScript object. Just remove the JSON.stringify() call and pass req.body directly to base.create():

app.post('/api/create-record', jsonParser, async (req, res) => { 
    const recordInfo = req.body;   
    console.log(recordInfo); 
    base.create(recordInfo, function(err, result) {  
        if (err) {console.log(err); res.json(err)} else {console.log(result), res.json('Created successfully!')}
    });   
})

That should fix it since you’re now passing the correct object format to Airtable.