'react-hook-forms upload/save to an object at FaunaDB

I'm trying to upload/save to an object at FaunaDB. Specifically, I'm trying to upload a string to a jobProfile object:

data: {
 "jobProfile": {
    "image": ""
    "coverImage": ""
 }
}

But when I'm uploading the strings using the submit button, they get saved in the root like so:

data: {
  "image": ""
  "coverImage": ""
}

I've created a main component where react-hook-forms gets default values from userData pulled in via useSWR through a prop:

import { useForm } from "react-hook-form"

import ImageInput from "./ImageInput"

export default function Inputs({ userData }) {
  const defaultValues = {
    image: userData?.jobProfile?.image ? userData?.jobProfile?.image : "",
    coverImage: userData?.jobProfile?.coverImage ? userData?.jobProfile?.coverImage : ""
  }

  const { register, handleSubmit } = useForm({ defaultValues })

  const handleUpdateUser = async (data) => {
    const { image, coverImage } = data
    try {
      await fetch("/api/updateProfile", {
        method: "PUT",
        body: JSON.stringify({
          image, coverImage
        }),
        headers: {
          "Content-Type": "application/json",
        },
      })
      alert(`submitted data: ${JSON.stringify(data)}`)
    } catch (err) {
      console.error(err)
    }
  }

  return (
    <form onSubmit={handleSubmit(handleUpdateUser)}>
      <div className="py-4">
        <ImageInput register={register} />
      </div>
      <button type="submit">Update</button>
    </form>
  )
}

Below is my ImageInput.jsx component I import within the main component. This component contains the input fields for image and coverImage:

//ImageInput.jsx
export default function ImageInput({ register }) {
  return (
    <div className="grid gap-4">
      <div>
        <label
          htmlFor="company-website"
          className="block text-sm font-medium text-gray-700"
        >
          Profilbillede
        </label>
        <div className="relative mt-1 rounded-md shadow-sm">
          <div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
            <span className="text-gray-500 sm:text-sm">https://</span>
          </div>
          <input
            type="text"
            name="company-website"
            id="company-website"
            className="block w-full rounded-md border-gray-300 pl-16 focus:border-indigo-500 focus:ring-indigo-500 sm:pl-14 sm:text-sm"
            placeholder="www.example.com/profile/avatar"
            {...register("jobProfile.image", {})}
          />
        </div>
        <p className="mt-2 text-sm text-gray-500" id="email-description">
          Indsæt billede URL (link) fra eksempelvis Facebook eller LinkedIn.
        </p>
      </div>

      <div>
        <label
          htmlFor="company-website"
          className="block text-sm font-medium text-gray-700"
        >
          Coverbillede
        </label>
        <div className="relative mt-1 rounded-md shadow-sm">
          <div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
            <span className="text-gray-500 sm:text-sm">https://</span>
          </div>
          <input
            type="text"
            name="company-website"
            id="company-website"
            className="block w-full rounded-md border-gray-300 pl-16 focus:border-indigo-500 focus:ring-indigo-500 sm:pl-14 sm:text-sm"
            placeholder="www.example.com/profile/avatar"
            {...register("jobProfile.coverImage", {})}
          />
        </div>
        <p className="mt-2 text-sm text-gray-500" id="email-description">
          Indsæt billede URL (link) fra eksempelvis Facebook eller LinkedIn.
        </p>
      </div>
    </div>
  )
}
//updateProfile.js
import { updateProfileInfo } from "@/utils/Fauna"
import { getSession } from "next-auth/react"

export default async (req, res) => {
  const session = await getSession({ req })
  if (!session) return res.status(401)

  const userId = session.user.id
  if (req.method !== "PUT") {
    return res.status(405).json({ msg: "Method not allowed" })
  }

  const { image, coverImage } =
    req.body
  try {
    const updated = await updateProfileInfo(
      userId,
      image,
      coverImage
    )
    return res.status(200).json(updated)
  } catch (err) {
    console.error(err)
    res.status(500).json({ msg: "Something went wrong." })
  }
  res.end()
}
//fauna.js
import * as Fauna from "faunadb"

const faunaClient = new Fauna.Client({
  secret: process.env.FAUNA_ADMIN_SECRET,
  scheme: "https",
  domain: "db.eu.fauna.com",
  port: 443,
})
const q = Fauna.query

const getUserById = async (id) => {
  const userData = await faunaClient.query(
    q.Get(q.Ref(q.Collection("users"), id))
  )
  delete userData.data.emailVerified
  delete userData.data.createdAt
  delete userData.data.updatedAt
  delete userData.data.ssn
  return userData.data
}

const updateProfileInfo = async (
  userId,
  image,
  coverImage
) => {
  return await faunaClient.query(
    q.Update(q.Ref(q.Collection("users"), userId), {
      data: {
        image,
        coverImage
      },
    })
  )
}

module.exports = {
  getUserById,
  updateProfileInfo
}

Can you see what I'm doing wrong?



Solution 1:[1]

In your updateProfileInfo function in fauna.js you should have

data: {
  jobProfile: {
    image,
    coverImage
  }
},

not:

data: {
  image,
  coverImage
},

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Fedor Parfenov