Как кодировать и анализировать / декодировать строку вложенного запроса Javascript

Я отправляю данные формы из React Hook Form в Netlify через их функцию, созданную с помощью отправки. У меня нет проблем с кодированием значений отдельных полей формы, но теперь я пытаюсь кодировать массив объектов.

Вот пример данных моей формы:

      {
  _id: "12345-67890-asdf-qwer",
  language: "Spanish",
  formId: "add-registration-form",
  got-ya: "",
  classType: "Private lessons",
  size: "1",
  days: [
    {
      day: "Monday",
      start: 08:00",
      end: "09:30"
    },
    {
      day: "Wednesday",
      start: "08:00",
      end: "09:30"
    }
  ]
}

Единственная проблема, с которой я столкнулся, связана с массивом дней. Я пробовал различными способами кодировать это, и это функция, с которой я сейчас работаю (что не идеально):

       const encode = (data) => {
    return Object.keys(data).map(key => {
      let val = data[key]
      if (val !== null && typeof val === 'object') val = encode(val)
      return `${key}=${encodeURIComponent(`${val}`.replace(/\s/g, '_'))}`
    }).join('&')
  }

Я пробовал использовать такую ​​библиотеку, как qs, для преобразования данных в строки, но не могу понять, как это сделать.

А вот функция отправки данных в Netlify:

      // Handles the post process to Netlify so I can access their serverless functions
   const handlePost = (formData, event) => {
    event.preventDefault()
    fetch(`/`, {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: encode({ "form-name": 'add-registration-form', ...formData }),
    })
      .then((response) => {
        if(response.status === 200) {
          navigate("../../")
        } else {
          alert("ERROR!")
        }
        console.log(response)
      })
      .catch((error) => {
        setFormStatus("error")
        console.log(error)
      })
  }

Наконец, вот образец моего файла, созданного для получения и анализа закодированных данных:

      const sanityClient = require("@sanity/client")
const client = sanityClient({
  projectId: process.env.GATSBY_SANITY_PROJECT_ID,
  dataset: process.env.GATSBY_SANITY_DATASET,
  token: process.env.SANITY_FORM_SUBMIT_TOKEN,
  useCDN: false,
})

const { nanoid } = require('nanoid');

exports.handler = async function (event, context, callback) {
  
  // Pulling out the payload from the body
  const { payload } = JSON.parse(event.body)

  // Checking which form has been submitted
  const isAddRegistrationForm = payload.data.formId === "add-registration-form"

  // Build the document JSON and submit it to SANITY
  if (isAddRegistrationForm) {


    // How do I decode the "days" data from payload?
    let schedule = payload.data.days.map(d => (
    {
      _key: nanoid(),
      _type: "classDayTime",
      day: d.day,
      time: {
        _type: "timeRange",
        start: d.start,
        end: d.end
      }
    }
  ))


    const addRegistrationForm = {
      _type: "addRegistrationForm",
      _studentId: payload.data._id,
      classType: payload.data.classType,
      schedule: schedule,
      language: payload.data.language,
      classSize: payload.data.size,
    }
    const result = await client.create(addRegistrationForm).catch((err) => console.log(err))
  }
  
  callback(null, {
    statusCode: 200,
  })
}

Итак, как мне правильно закодировать данные моей формы с помощью вложенного массива объектов перед их отправкой в ​​Netlify? А затем в функции Netlify, как мне проанализировать / декодировать эти данные, чтобы иметь возможность отправить их в Sanity?

1 ответ

Итак, библиотека qs все-таки оказалась моим спасителем. Я просто не реализовал это правильно раньше. Итак, с той же структурой данных формы, просто убедитесь, что вы импортировали qs в файл компонента формы:

      import qs from 'qs'

а затем сделайте свою функцию кодирования красивой и лаконичной с помощью:

           // Transforms the form data from the React Hook Form output to a format Netlify can read
      const encode = (data) => {
        return qs.stringify(data)
      } 

Затем используйте эту функцию кодирования в своей функции отправки дескриптора для формы:

       // Handles the post process to Netlify so we can access their serverless functions
   const handlePost = (formData, event) => {
    event.preventDefault()

    fetch(`/`, {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: encode({ "form-name": 'add-registration-form', ...formData }),
    })
      .then((response) => {
        reset()
        if(response.status === 200) {
          alert("SUCCESS!")
        } else {
          alert("ERROR!")
        }
        console.log(response)
      })
      .catch((error) => {
        console.log(error)
      })
  }

Наконец, вот как должен выглядеть ваш файл Netlify submission-created.js примерно так:

      const sanityClient = require("@sanity/client")
const client = sanityClient({
  projectId: process.env.GATSBY_SANITY_PROJECT_ID,
  dataset: process.env.GATSBY_SANITY_DATASET,
  token: process.env.SANITY_FORM_SUBMIT_TOKEN,
  useCDN: false,
}) 
const qs = require('qs')
const { nanoid } = require('nanoid');

exports.handler = async function (event, context, callback) {
  
  // Pulling out the payload from the body
  const { payload } = JSON.parse(event.body)


  // Checking which form has been submitted
  const isAddRegistrationForm = payload.data.formId === "add-registration-form"

  // Build the document JSON and submit it to SANITY
  if (isAddRegistrationForm) {
    const parsedData = qs.parse(payload.data)
    
    let schedule = parsedData.days
      .map(d => (
        {
          _key: nanoid(),
          _type: "classDayTime",
          day: d.day,
          time: {
            _type: "timeRange",
            start: d.start,
            end: d.end
          }
        }
      ))

    const addRegistrationForm = {
      _type: "addRegistrationForm",
      submitDate: new Date().toISOString(),
      _studentId: parsedData._id,
      classType: parsedData.classType,
      schedule: schedule,
      language: parsedData.language,
      classSize: parsedData.size,
    }
    const result = await client.create(addRegistrationForm).catch((err) => console.log(err))
  }
  
  callback(null, {
    statusCode: 200,
  })
}
Другие вопросы по тегам