'Uncaught (in promise) SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data - REACT

So I've been trying to create this "register" user with the MERN stack. But in the console, I see an error that is very difficult for me to understand. I don't really understand where the error is exactly.

It says Uncaught (in promise) SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data

but I don't understand where that is. Can someone enlighten me please?

This is my server index.js

const express = require("express");
const app = express();
const cors = require("cors");
const mongoose = require("mongoose");
const User = require("./models/user.model");
const jwt = require("jsonwebtoken");
const bcrypt = require("bcryptjs");

app.use(cors());
app.use(express.json());

mongoose.connect("mongodb://localhost:27017/tribeto");

app.post("/api/register", async (req, res) => {
  console.log(req.body);
  try {
    const newPassword = await bcrypt.hash(req.body.password, 10);
    await User.create({
      companyName: req.body.companyName,
      firstName: req.body.firstName,
      lastName: req.body.lastName,
      jobTitle: req.body.jobTitle,
      email: req.body.email,
      phone: req.body.phone,
      password: newPassword,
    });
    res.json({ status: "ok" });
  } catch (err) {
    res.json({ status: "error", error: "Duplicate email" });
  }
});

app.post("/api/login", async (req, res) => {
  const user = await User.findOne({
    email: req.body.email,
  });

  if (!user) {
    return { status: "error", error: "Invalid login" };
  }

  const isPasswordValid = await bcrypt.compare(
    req.body.password,
    user.password
  );

  if (isPasswordValid) {
    const token = jwt.sign(
      {
        name: user.name,
        email: user.email,
      },
      "secret123"
    );

    return res.json({ status: "ok", user: token });
  } else {
    return res.json({ status: "error", user: false });
  }
});

app.get("/api/quote", async (req, res) => {
  const token = req.headers["x-access-token"];

  try {
    const decoded = jwt.verify(token, "secret123");
    const email = decoded.email;
    const user = await User.findOne({ email: email });

    return res.json({ status: "ok", quote: user.quote });
  } catch (error) {
    console.log(error);
    res.json({ status: "error", error: "invalid token" });
  }
});

app.post("/api/quote", async (req, res) => {
  const token = req.headers["x-access-token"];

  try {
    const decoded = jwt.verify(token, "secret123");
    const email = decoded.email;
    await User.updateOne({ email: email }, { $set: { quote: req.body.quote } });

    return res.json({ status: "ok" });
  } catch (error) {
    console.log(error);
    res.json({ status: "error", error: "invalid token" });
  }
});

app.listen(3000, () => {
  console.log("Server started on 3000");
});

And here is the user.model.js that I'm using:

const mongoose = require("mongoose");

const User = new mongoose.Schema(
  {
    companyName: { type: String, required: true, unique: true },
    firstName: { type: String, required: true },
    lastName: { type: String, required: true },
    jobTitle: { type: String, required: true },
    email: { type: String, required: true, unique: true },
    phone: { type: String, required: true },
    password: { type: String, required: true },
  },
  { collection: "user-data" }
);

const model = mongoose.model("UserData", User);
module.exports = model;

And here is the implementation in my component:

import React, { useState } from "react";
import { ChevronRightIcon } from "@heroicons/react/solid";

export default function Example() {
  const [companyName, setCompanyName] = useState("");
  const [firstName, setFirstName] = useState("");
  const [lastName, setLastName] = useState("");
  const [jobTitle, setJobTitle] = useState("");
  const [email, setEmail] = useState("");
  const [phone, setPhone] = useState("");
  const [password, setPassword] = useState("");

  async function registerUser(event) {
    event.preventDefault();

    const response = await fetch("http://localhost:3000/api/register", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        companyName,
        firstName,
        lastName,
        jobTitle,
        email,
        phone,
        password,
      }),
    });

    const data = await response.json();
  }

  return (
    <div className="relative bg-gray-50 dark:bg-gray-900 overflow-hidden">
      <div
        className="hidden sm:block sm:absolute sm:inset-0"
        aria-hidden="true"
      >
        <svg
          className="absolute bottom-0 right-0 transform translate-x-1/2 mb-48 text-gray-700 lg:top-0 lg:mt-28 lg:mb-0 xl:transform-none xl:translate-x-0"
          width={364}
          height={384}
          viewBox="0 0 364 384"
          fill="none"
        >
          <defs>
            <pattern
              id="eab71dd9-9d7a-47bd-8044-256344ee00d0"
              x={0}
              y={0}
              width={20}
              height={20}
              patternUnits="userSpaceOnUse"
            >
              <rect x={0} y={0} width={4} height={4} fill="currentColor" />
            </pattern>
          </defs>
          <rect
            width={364}
            height={384}
            fill="url(#eab71dd9-9d7a-47bd-8044-256344ee00d0)"
          />
        </svg>
      </div>
      <div className="relative pt-6 pb-16 sm:pb-24">
        <main className="mt-24">
          <div className="mx-auto max-w-7xl">
            <div className="lg:grid lg:grid-cols-12 lg:gap-8">
              <div className="px-4 sm:px-6 sm:text-center md:max-w-2xl md:mx-auto lg:col-span-6 lg:text-left lg:flex lg:items-center">
                <div>
                  <a
                    href="/partner"
                    className="inline-flex items-center text-white bg-gray-900 rounded-full p-1 pr-2 sm:text-base lg:text-sm xl:text-base hover:text-gray-200"
                  >
                    <span className="px-3 py-0.5 text-white text-xs font-semibold leading-5 uppercase tracking-wide bg-btncolor rounded-full">
                      Become a Partner
                    </span>
                    <span className="ml-4 text-sm">Visit our partner page</span>
                    <ChevronRightIcon
                      className="ml-2 w-5 h-5 text-gray-500"
                      aria-hidden="true"
                    />
                  </a>
                  <h1 className="mt-4 text-4xl tracking-tight font-extrabold text-gray-900 dark:text-white sm:mt-5 sm:leading-none lg:mt-6 lg:text-5xl xl:text-6xl">
                    <span className="md:block">Credibility through</span>{" "}
                    <span className="text-primary md:block">Transparency</span>
                  </h1>
                  <p className="mt-3 text-base text-gray-900 dark:text-gray-300 sm:mt-5 sm:text-xl lg:text-lg xl:text-xl">
                    Tribeto transforms the way companies interact with their
                    customers through video reviews.
                  </p>
                </div>
              </div>
              <div className="mt-16 sm:mt-24 lg:mt-0 lg:col-span-6">
                <div className="bg-white dark:bg-gray-800 sm:max-w-md sm:w-full sm:mx-auto sm:rounded-lg sm:overflow-hidden drop-shadow-lg">
                  <div className="px-4 py-8 sm:px-10">
                    <div>
                      <p className="text-2xl m-2 text-center font-bold text-gray-700 dark:text-white">
                        Create an account for free
                      </p>
                      <p className="text-sm text-center font-medium text-gray-700 dark:text-white">
                        And feel the power of video reviews today.
                      </p>
                    </div>

                    <div className="mt-6 relative">
                      <div
                        className="absolute inset-0 flex items-center"
                        aria-hidden="true"
                      >
                        <div className="w-full border-t border-gray-300 dark:border-gray-600" />
                      </div>
                      <div className="relative flex justify-center text-sm"></div>
                    </div>

                    <div className="mt-6">
                      <form onSubmit={registerUser} className="space-y-6">
                        <div>
                          <label htmlFor="company-name" className="sr-only">
                            Company name
                          </label>
                          <input
                            value={companyName}
                            onChange={(e) => setCompanyName(e.target.value)}
                            type="text"
                            placeholder="Company name"
                            required
                            className="block w-full shadow-sm focus:ring-primary focus:border-primary sm:text-sm border-gray-300 rounded-md dark:bg-gray-700 dark:border-gray-700 dark:placeholder-gray-300"
                          />
                        </div>

                        <div className="grid grid-cols-6 gap-6">
                          <div className="col-span-6 sm:col-span-3">
                            <label htmlFor="first-name" className="sr-only">
                              First name
                            </label>
                            <input
                              value={firstName}
                              onChange={(e) => setFirstName(e.target.value)}
                              type="text"
                              placeholder="First name"
                              required
                              className="block w-full shadow-sm focus:ring-primary focus:border-primary sm:text-sm border-gray-300 rounded-md dark:bg-gray-700 dark:border-gray-700 dark:placeholder-gray-300"
                            />
                          </div>

                          <div className="col-span-6 sm:col-span-3">
                            <label htmlFor="last-name" className="sr-only">
                              Last name
                            </label>
                            <input
                              value={lastName}
                              onChange={(e) => setLastName(e.target.value)}
                              type="text"
                              placeholder="Last name"
                              required
                              className="block w-full shadow-sm focus:ring-primary focus:border-primary sm:text-sm border-gray-300 rounded-md dark:bg-gray-700 dark:border-gray-700 dark:placeholder-gray-300"
                            />
                          </div>
                        </div>

                        <div>
                          <label htmlFor="job-title" className="sr-only">
                            Job title
                          </label>
                          <input
                            value={jobTitle}
                            onChange={(e) => setJobTitle(e.target.value)}
                            type="text"
                            placeholder="Job title"
                            required
                            className="block w-full shadow-sm focus:ring-primary focus:border-primary sm:text-sm border-gray-300 rounded-md dark:bg-gray-700 dark:border-gray-700 dark:placeholder-gray-300"
                          />
                        </div>

                        <div>
                          <label htmlFor="work-email" className="sr-only">
                            Work email
                          </label>
                          <input
                            value={email}
                            onChange={(e) => setEmail(e.target.value)}
                            type="email"
                            placeholder="Work email"
                            required
                            className="block w-full shadow-sm focus:ring-primary focus:border-primary sm:text-sm border-gray-300 rounded-md dark:bg-gray-700 dark:border-gray-700 dark:placeholder-gray-300"
                          />
                        </div>

                        <div>
                          <label htmlFor="phone" className="sr-only">
                            Phone
                          </label>
                          <input
                            value={phone}
                            onChange={(e) => setPhone(e.target.value)}
                            type="text"
                            placeholder="Phone number"
                            required
                            className="block w-full shadow-sm focus:ring-primary focus:border-primary sm:text-sm border-gray-300 rounded-md dark:bg-gray-700 dark:border-gray-700 dark:placeholder-gray-300"
                          />
                        </div>

                        <div>
                          <label htmlFor="password" className="sr-only">
                            Password
                          </label>
                          <input
                            value={password}
                            onChange={(e) => setPassword(e.target.value)}
                            type="password"
                            placeholder="Password"
                            required
                            className="block w-full shadow-sm focus:ring-primary focus:border-primary sm:text-sm border-gray-300 rounded-md dark:bg-gray-700 dark:border-gray-700 dark:placeholder-gray-300"
                          />
                        </div>

                        <div>
                          <button
                            type="submit"
                            value="Register"
                            className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-gray-900 hover:bg-btnhover focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary"
                          >
                            Create your account
                          </button>
                        </div>
                        <fieldset className="">
                          <legend className="sr-only">Notifications</legend>
                          <div className="relative flex items-start">
                            <div className="flex items-center h-5">
                              <input
                                id="comments"
                                aria-describedby="comments-description"
                                name="comments"
                                type="checkbox"
                                className="focus:ring-primary h-4 w-4 text-primary border-gray-300 rounded"
                              />
                            </div>
                            <div className="ml-3 text-sm">
                              <label
                                htmlFor="comments"
                                className="font-medium text-gray-700 dark:text-white"
                              >
                                Don't be shy
                              </label>
                              <span
                                id="comments-description"
                                className="text-gray-500 dark:text-gray-300"
                              >
                                <span className="sr-only"></span> click here if
                                you want to speak to an expert from Tribeto to
                                help you get started.
                              </span>
                            </div>
                          </div>
                        </fieldset>
                      </form>
                    </div>
                  </div>
                  <div className="px-4 py-6 bg-gray-50 dark:bg-gray-700 border-t-2 border-gray-200 dark:border-gray-800 sm:px-10">
                    <p className="text-xs leading-5 text-gray-500 dark:text-white">
                      By signing up, you agree to our{" "}
                      <a
                        href="#"
                        className="font-medium text-gray-900 dark:text-primary hover:underline"
                      >
                        Terms
                      </a>
                      ,{" "}
                      <a
                        href="#"
                        className="font-medium text-gray-900 dark:text-primary hover:underline"
                      >
                        Data Policy
                      </a>{" "}
                      and{" "}
                      <a
                        href="#"
                        className="font-medium text-gray-900 dark:text-primary hover:underline"
                      >
                        Cookies Policy
                      </a>
                      .
                    </p>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </main>
      </div>
    </div>
  );
}


Sources

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

Source: Stack Overflow

Solution Source