1

i'm trying to code a feature on my website that lets the user upload their own profile picture. It's also my first time using the MERN stack so here's the code i wrote:

Frontend:

Settings.tsx 

import React, { useEffect, useState } from "react";
import axios from "axios";
import Image from "next/image";
import iconDefault from "../assets/random/user.png";

const Settings = () => {
  const [isEditing, setIsEditing] = useState<boolean>(false);
  const [file, setFile] = useState<any | null>(null);
  const [picture, setPicture] = useState<any | null>(null);

  const cookies = new Cookies();
  const user = getUserCookie();
  const [updatedUser, setUpdatedUser] = useState<User>(user);

  const handleEdit = () => {
    setIsEditing(!isEditing);
  };

  const handleInputChange = (
    e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
  ) => {
    const { name, value } = e.target;
    setUpdatedUser((prevUser) => ({
      ...prevUser,
      [name]: value,
    }));
  };

  const upload_preset = ".....";
  const cloud_name = ".....";

  const submitImage = async () => {
    const data = new FormData();
    data.append("file", file);
    data.append("upload_preset", upload_preset);
    data.append("cloud_name", cloud_name);

    try {
      const res = await axios.post(
        `https://api.cloudinary.com/v1_1/${cloud_name}/image/upload`,
        data
      );
      const cloudinaryUrl = res.data.secure_url;
      setPicture(cloudinaryUrl);

      const updatedUserWithImage = { ...updatedUser, icon: cloudinaryUrl };
      await editUser(updatedUserWithImage);
    } catch (err) {
      console.log("error uploading icon", err);
    }
  };

  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    try {
      if (file) {
        await submitImage();
      } else {
        await editUser(updatedUser);
      }
      window.location.reload();
    } catch (err) {
      console.log("error updating icon: ", err);
    }
  };

  const editUser = async (updatedUser: User) => {
    const token = cookies.get("token");

    try {
      await axios.patch(
        process.env.MONGODB_URL + `/users/${user?._id}`,
        updatedUser,
        {
          // .patch(`http://localhost:3005` + `/users/${user?._id}`, updatedUser, {
          headers: {
            Authorization: `Bearer ${token}`,
          },
        }
      );

      const response = await axios.get(
        process.env.MONGODB_URL + `/users/${user?._id}`,
        {
          headers: {
            Authorization: `Bearer ${token}`,
          },
        }
      );

      const updatedUserFromServer = response.data;
      document.cookie = `user=${JSON.stringify(updatedUserFromServer)}; path=/`;
      console.log("Updated User:", updatedUserFromServer);
    } catch (err) {
      console.log("error updating user: ", err);
    }
  };

  return (
    <div className="settings">
      <main>
        <header className="header__welcome card ">
          <div>
            {user ? <h1>Hello, {user.name}!</h1> : <h1>Loading user...</h1>}
            <h2>Edit here your profile info</h2>
          </div>
          
        </header>
        <div className="form-container">
          <form onSubmit={handleSubmit} className="form-settings">
            <div className="form-settings__left">
              <div>
                {user.icon ? (
                  <Image
                    className="icon-settings"
                    src={user.icon}
                    width="400"
                    height="400"
                    alt="icon"
                  />
                ) : (
                  <Image
                    className="icon-settings"
                    src={iconDefault}
                    width="400"
                    height="400"
                    alt="iconDefault"
                  />
                )}
              </div>

              <div className="rainbow__button">
                <label htmlFor="icon">Edit profile picture</label>
                <input
                  type="file"
                  name="icon"
                  className="input-settings"
                  onChange={(e) => setFile(e.target.files?.[0] || null)}
                />
              </div>
            </div>
        
              {......}
              <div className="buttons">
                <button
                  className="buttons__addtask rainbow__button"
                  type="submit"
                >
                  Save changes
                </button>
                <hr></hr>
                <DeleteUser />
              </div>
            </div>
          </form>
        </div>
      </main>
    </div>
  );
};

export default Settings;

But when i choose the image and submit the form i get this error:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://api.cloudinary.com/v1_1/---/image/upload. (Reason: header ‘authorization’ is not allowed according to header ‘Access-Control-Allow-Headers’ from CORS preflight response).

XHRPOST https://api.cloudinary.com/v1_1/---/image/upload

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://api.cloudinary.com/v1_1/----/image/upload. (Reason: CORS request did not succeed). Status code: (null).

error uploading icon

i put my preset key on Cloudinary to "unsigned" already but it still doesn't work, i don't know what else to do. Can anyone help?

edit: i'd like to mention that this happened before but i managed to fix it: i realised that the mongodb document/user i was trying to update from the frontend didn't have a "icon" value, so i created it and it worked just fine, i even changed profile pictures a few times on the same user and it worked. Now it's happening again and i'm not sure what's the reason this time.

queercoded
  • 55
  • 9
  • You may refer to this document for the [Axios having CORS issues](https://stackoverflow.com/questions/50949594/axios-having-cors-issue). And as shown in the [Cloudinary example here](https://glitch.com/~cld-signed-upload-examples), you could consider to use the JavaScript `fetch` when posting your request to Cloudinary API. – epasos_573 Jul 25 '23 at 04:43
  • 1
    @epasos_573 oh damn.... thank you so much it worked as soon as i tried it! – queercoded Jul 25 '23 at 13:29

0 Answers0