Fetching data from Formik form using Gatsby and use Netlify functions to post into Sanity

answered
#1

Hi,

I’m new using Netlify functions, I’m using Gatsby with Sanity on Netlfy. I’m trying to use function for user to post new job into sanity using Netlify function. I’ve started setting up a test form but I’m struggling to get everything working together.

Here my form using formik with yup:

const jobPostSchema = Yup.object().shape({
  title: Yup.string()
    .min(2, 'Too Short!')
    .max(50, 'Too Long!')
    .required('Job title is required.'),
  email: Yup.string()
    .email('Invalid email address')
    .required('Email is required!'),
})

const encode = data => {
  return Object.keys(data)
    .map(key => encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))
    .join('&')
}

export default class NewJob extends React.Component {
  render() {
    return (
      <Layout>
        <ContentWrapFull>
          <PageHeading>Post a job</PageHeading>

          <Formik
            initialValues={{ title: '', email: '' }}
            validationSchema={jobPostSchema}
            onSubmit={(payload, { setSubmitting }) => {
              fetch('/?no-cache=1', {
                method: 'POST',
                headers: {
                  'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: encode({ 'form-name': 'jobsubmit', payload }),
              })
              alert(payload.title)
              console.log(payload)
              setSubmitting(false)
            }}
          >
            {({
              values,
              errors,
              dirty,
              touched,
              handleChange,
              handleBlur,
              handleSubmit,
              handleReset,
              isSubmitting,
              /* and other goodies */
            }) => (
              <form
                name="jobsubmit"
                method="post"
                action="/thanks/"
                data-netlify="true"
                onSubmit={handleSubmit}
              >
                <p>
                  <FormLabel>
                    Job position*
                    <br />
                    <FormInput
                      type="text"
                      name="title"
                      onChange={handleChange}
                      onBlur={handleBlur}
                      value={values.title}
                    />
                    {errors.title && touched.title && errors.title}
                  </FormLabel>
                </p>
                <p>
                  <FormLabel>
                    Application Email or URL
                    <br />
                    <FormInput
                      type="email"
                      name="email"
                      onChange={handleChange}
                      onBlur={handleBlur}
                      value={values.email}
                    />
                    {errors.email && touched.email && errors.email}
                  </FormLabel>
                </p>

                <button
                  type="button"
                  onClick={handleReset}
                  disabled={!dirty || isSubmitting}
                >
                  Reset
                </button>
                <button type="submit" disabled={isSubmitting}>
                  Submit
                </button>
              </form>
            )}
          </Formik>
        </ContentWrapFull>
      </Layout>
    )
  }
}

Here my function:

const sanityClient = require('@sanity/client')
require('dotenv').config({
  path: `.env.${process.env.NODE_ENV}`,
})
const client = sanityClient({
  projectId: 'idnumber',
  dataset: 'databasename',
  token: process.env.SANITY_TOKEN_WRITE,
})

exports.handler = async function(event, context, callback) {

  let payload = JSON.stringify(event.body).payload

  let result = await client.create({ _type: 'job', ...payload })

  callback(null, {
    statusCode: 200,
    body: JSON.stringify(result),
  })

  console.log(data)
}

Any suggestion would be welcome, thank you.

#2

Hi Jerome,

Better to back up a few steps and make sure all the basic pieces work before trying to debug :slight_smile:

First off, does your form work in Netlify? You get a 200 when POST’ing, the data from the POST is saved and shown in your netlify dashboard? If so, great start! If not, check out our forms debugging articles such as [Common Issue] How to debug your form as well as "Page Not Found" when submitting form and finally since you use gatsby, also see this blog post about gatsby+netlify that touches on form setup

If that does already work, awesome! That’s probably the biggest hurdle. Next up, how are you attempting to process the POST? Perhaps using an event triggered function? If so, this article may point the way: Debugging event-triggered functions

Let us know more about what you’re doing and how you’re trying to do it and we’ll probably be able to give some more specific guidance, short of debugging your code (which is only half of the picture :))

#3

3 suggestions:

First, inside of your function you no longer need to use something like dotenv package. You can just do something like this:

const sanityClient = require('@sanity/client')
const { 
  SANITY_TOKEN_WRITE
} = process.env

const client = sanityClient({
  projectId: 'idnumber',
  dataset: 'databasename',
  token: SANITY_TOKEN_WRITE,
})

Make sure you set your SANITY_TOKEN_WRITE environment variable in the site settings.

And second, with async functions you no longer need the callback in your function, so you can do something like this:

exports.handler = async function(event, context, callback) {

  let payload = JSON.stringify(event.body).payload

  let result = await client.create({ _type: 'job', ...payload })
  console.log('result', result)
  return {
    statusCode: 200,
    body: JSON.stringify(result),
  }

}

And third, you can test out these functions locally with the new netlify dev command.

npm install netlify-cli -g

# then run the functions locally

netlify dev

More info on the dev command can be found here https://scotch.io/tutorials/netlify-dev-the-power-of-netlify-on-your-local-computer

1 Like
#4

Thank you so much David making some progress, When I’m checking the functions using Netlify dev getting some data but not the payload data from my form, any suggestions?

#5

Not sure about that.

What happens when you deploy the live function to netlify?

1 Like
#6

Here the function log after being deployed

    4:52:25 PM: submission-created invoked
    4:52:26 PM: Unable to import module 'submission-created': Error    at Function.Module._resolveFilename (module.js:547:15)    at Function.Module._load (module.js:474:25)    at Module.require (module.js:596:17)    at require (internal/module.js:11:18)    at Object.<anonymous> (/var/task/submission-created.js:1:84)    at Module._compile (module.js:652:30)    at Object.Module._extensions..js (module.js:663:10)    at Module.load (module.js:565:32)    at tryModuleLoad (module.js:505:12)    at Function.Module._load (module.js:497:3)
    4:52:53 PM: submission-created invoked
    4:52:53 PM: Unable to import module 'submission-created': Error    at Function.Module._load (module.js:474:25)    at Module.require (module.js:596:17)    at require (internal/module.js:11:18)    at Object.<anonymous> (/var/task/submission-created.js:1:84)    at Module._compile (module.js:652:30)    at Object.Module._extensions..js (module.js:663:10)    at Module.load (module.js:565:32)    at tryModuleLoad (module.js:505:12)    at Function.Module._load (module.js:497:3)
#7

Sounds like the module is not found.

Is there a package.json file inside your functions folder with the @sanity/client package (and any other dep used in functions)