👀 See Sanity in action: Watch product demo now →

How to Send Data From a Form in Next.js

24 replies
Last updated: Nov 8, 2021
Hi everyone. I have been working on sending data from a form in NextJS. The connection works, but I’m having an issue where all data is being imported as a string. For example, numbers are being imported as a string and any select options are completely ignored. Any suggestions?
Nov 8, 2021, 3:50 PM
Hiya Racheal (Hero):

const sanityClient = require('@sanity/client')


const client = sanityClient({

projectId: 'xxxxx',

dataset: 'production',

apiVersion: '2021-03-25',

useCdn: false,

token:

process.env.SANITY_API_WRITE_TOKEN ||

'xxxxx',

})


export default async function addDebt(_req_, _res_) {

const {

lender,

amountFunded,

balance,

dateFunded,

frequency,

numberOfPayments,

payback,

status,

} = JSON.parse(_req_.body)

try {

await client.create({

_type: 'debt',

lender,

amountFunded,

balance,

dateFunded,

frequency,

numberOfPayments,

payback,

status,

})

} catch (err) {

console.error(err)
`return
res.status(500).json({ message:
Couldn't submit debt
, err })`
}
`return
res.status(200).json({ message:
Debt ${_res_._id} has been created
})`
}
Nov 8, 2021, 7:08 PM
Note that this is essentially a test. I realize you may have received some notifications of earlier questions, which I removed, since I resolved them. My primary issue now is just getting these values to populate other than strings, only
Nov 8, 2021, 7:13 PM
Hmm, that seems right. Can you share an example of the data you're passing to it if you console.log it?
Nov 8, 2021, 7:16 PM
Hmm, that seems right. Can you share an example of the data you're passing to it if you console.log it?
Nov 8, 2021, 7:16 PM
Here’s a screenshot of what I get from Sanity Studio:
Nov 8, 2021, 7:16 PM
The code provided above is from the API. I can also share the form code, if you’d like
Nov 8, 2021, 7:18 PM
I'm curious if the form is passing the incorrect format to that function. I can't see a reason why the request would mutate the type of the data, so maybe it's happening before it even enters that API request.
Nov 8, 2021, 7:20 PM
Perhaps! Here’s the code from the form:
Nov 8, 2021, 7:23 PM
import { useState } from 'react'
import { useForm } from ‘react-hook-form’

export default function DebtAddForm() {
const [formData, setFormData] = useState()
const [isSubmitting, setIsSubmitting] = useState(false)
const [hasSubmitted, setHasSubmitted] = useState(false)
const {
register,
handleSubmit,
formState: { errors },
} = useForm()

const onSubmit = async (
_data_) => {
setIsSubmitting(true)
let response
setFormData(
_data_)
try {
response = await fetch(‘/api/addDebt’, {
method: ‘POST’,
body: JSON.stringify(
_data_),
type: ‘application/json’,
})
setIsSubmitting(false)
setHasSubmitted(true)
} catch (err) {
setFormData(err)
}
}

if (isSubmitting) {
return <h3>Submitting debt...</h3>
}
if (hasSubmitted) {
return (
<>
<h3>Debt submitted</h3>
<ul>
<li>
Lender: {formData.lender} <br />
Amount Funded: {formData.amountFunded} <br />
Balance: {formData.balance} <br />
dateFunded: {formData.dateFunded} <br />
frequency: {formData.frequency} <br />
numberOfPayments: {formData.numberOfPayments} <br />
payback: {formData.payback} <br />
status: {formData.status} <br />
</li>
</ul>
</>
)
}

return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<div>
<label className=‘text-xl block’>Lender</label>
<input
className={
mb-3 px-3 py-2 w-full border-2 border-gray-300 rounded shadow-sm ${
                            errors.lender ? ‘ring-2 ring-red-500’ : null
                        }
} type=‘text’
name=‘lender’
{...register(‘lender’, { required: true })}
/>
<span className=‘text-red-400 text-sm py-2’>
{errors?.lender?.message}
</span>
</div>
<div>
<label className=‘text-xl block’>Amount Funded</label>
<input
className={
mb-3 px-3 py-2 w-full border-2 border-gray-300 rounded shadow-sm ${
                            errors.amountFunded ? ‘ring-2 ring-red-500’ : null
                        }
} type=‘number’
name=‘amountFunded’
{...register(‘amountFunded’, { required: true })}
/>
<span className=‘text-red-400 text-sm py-2’>
{errors?.amountFunded?.message}
</span>
</div>
<div>
<label className=‘text-xl block’>Funded Date</label>
<input
className={
mb-3 px-3 py-2 w-full border-2 border-gray-300 rounded shadow-sm ${
                            errors.dateFunded ? ‘ring-2 ring-red-500’ : null
                        }
} type=‘date’
name=‘dateFunded’
{...register(‘dateFunded’, { required: true })}
/>
<span className=‘text-red-400 text-sm py-2’>
{errors?.amountFunded?.message}
</span>
</div>
<div>
<label className=‘text-xl block’>Current Balance</label>
<input
className={
mb-3 px-3 py-2 w-full border-2 border-gray-300 rounded shadow-sm ${
                            errors.balance ? ‘ring-2 ring-red-500’ : null
                        }
} type=‘number’
name=‘balance’
{...register(‘balance’, { required: true })}
/>
<span className=‘text-red-400 text-sm py-2’>
{errors?.balance?.message}
</span>
</div>
<div>
<label className=‘text-xl block’>Payback</label>
<input
className={
mb-3 px-3 py-2 w-full border-2 border-gray-300 rounded shadow-sm ${
                            errors.payback ? ‘ring-2 ring-red-500’ : null
                        }
} type=‘number’
name=‘payback’
{...register(‘payback’, { required: true })}
/>
<span className=‘text-red-400 text-sm py-2’>
{errors?.payback?.message}
</span>
</div>
<div>
<label className=‘text-xl block’>Payment</label>
<input
className={
mb-3 px-3 py-2 w-full border-2 border-gray-300 rounded shadow-sm ${
                            errors.payment ? ‘ring-2 ring-red-500’ : null
                        }
} type=‘number’
name=‘payment’
{...register(‘payment’, { required: true })}
/>
<span className=‘text-red-400 text-sm py-2’>
{errors?.payment?.message}
</span>
</div>
<div>
<label className=‘text-xl block’>Frequency</label>
<select
className={
mb-3 px-3 py-2 w-full border-2 border-gray-300 bg-white rounded shadow-sm ${
                            errors.frequency ? ‘ring-2 ring-red-500’ : null
                        }
} name=‘frequency’
{...register(‘frequency’, { required: true })}
>
<option value=‘Daily’>Daily</option>
<option value=‘Weekly’>Weekly</option>
<option value=‘Bi-Weekly’>Bi-Weekly</option>
<option value=‘Monthly’>Monthly</option>
</select>
<span className=‘text-red-400 text-sm py-2’>
{errors?.frequency?.message}
</span>
</div>
<div>
<label className=‘text-xl block’>numberOfPayments</label>
<input
className={
mb-3 px-3 py-2 w-full border-2 border-gray-300 rounded shadow-sm ${
                            errors.numberOfPayments ? ‘ring-2 ring-red-500’ : null
                        }
} type=‘number’
name=‘numberOfPayments’
{...register(‘numberOfPayments’, { required: true })}
/>
<span className=‘text-red-400 text-sm py-2’>
{errors?.numberOfPayments?.message}
</span>
</div>
<div>
<label className=‘text-xl block’>Status</label>
<select
className={
mb-3 px-3 py-2 w-full border-2 border-gray-300 bg-white rounded shadow-sm ${
                            errors.status ? ‘ring-2 ring-red-500’ : null
                        }
} name=‘status’
{...register(‘status’, { required: true })}
>
<option value=‘Current’>Current</option>
<option value=‘Default’>Default</option>
<option value=‘Restructured’>Restructured</option>
</select>
<span className=‘text-red-400 text-sm py-2’>
{errors?.status?.message}
</span>
</div>
</div>
<div>
<input type=‘submit’ className=‘mt-3 btn1’ />
</div>
</form>
)
}
Nov 8, 2021, 7:24 PM
Got it. It looks like you're stringifying your data:
body: JSON.stringify(data)
Nov 8, 2021, 7:26 PM
Got it. It looks like you're stringifying your data:
body: JSON.stringify(data)
Nov 8, 2021, 7:26 PM
🤦
Nov 8, 2021, 7:26 PM
Got it. It looks like you're stringifying your data:
body: JSON.stringify(data)
Nov 8, 2021, 7:26 PM
I was using an example to work from and completely missed it
Nov 8, 2021, 7:46 PM
I've been there!
Nov 8, 2021, 7:50 PM
Feeling like a dummy right now — When no longer stringifying the json data, the fields no longer populate at all. I’ve tried to avoid bothering you any further with this, but I’ve hit a wall. 😞
Nov 8, 2021, 9:50 PM
Feeling like a dummy right now — When no longer stringifying the json data, the fields no longer populate at all. I’ve tried to avoid bothering you any further with this, but I’ve hit a wall. 😞
Nov 8, 2021, 9:50 PM
Don't feel bad about asking questions! I love debugging stuff!
Nov 8, 2021, 9:51 PM
Feeling like a dummy right now — When no longer stringifying the json data, the fields no longer populate at all. I’ve tried to avoid bothering you any further with this, but I’ve hit a wall. 😞
Nov 8, 2021, 9:50 PM
I'll be back with a script/explanation
Nov 8, 2021, 9:53 PM
Thanks again! I really appreciate your time
Nov 8, 2021, 9:53 PM
So, first, we need to configure your JS Client. You're using Next, so we'll follow the usage here .
//client.js
import {createClient} from 'next-sanity'

export const sanityClient = createClient({
  projectId: 'your-project-id-from-sanity.json',
  dataset: 'your-dataset-name',
  apiVersion: '2021-03-25',
  token: '<http://sanity-auth-token-from-manage.sanity.io|sanity-auth-token-from-manage.sanity.io>',
  useCdn: true, // `false` if you want to ensure fresh data
})
Then, in your
onSubmit
function, you need to create an object that contains the fields in your form and their values, then use
client.create
. It's surprisingly straightforward if you already have the JS Client configured. Here's a pseudo code version of the script you'll need to run:
import { sanityClient } from './client'

const onSubmit = async () =&gt; {
 const doc = {
  _id = uuid4(), //or whatever package you use for generating a random ID
  ...formData //if the fields/values in data match the fields in your Sanity Schema you can use the spread operator to add them to your doc
  }
  client.create(doc).then(res =&gt; console.log(`Document was created, document ID is ${res._id}`)
}
Nov 8, 2021, 10:17 PM
Thank you
user M
. I'll toy around with this tonight :)
Nov 8, 2021, 11:59 PM
Thank you
user M
. I'll toy around with this tonight :)
Nov 8, 2021, 11:59 PM

Sanity.io – build remarkable experiences at scale

Sanity is a customizable solution that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Categorized in