Home > Enterprise >  Accessing API Cors in React
Accessing API Cors in React

Time:09-30

Hello I'm having a problem in updating my Image. In Postman I'm getting a cors error. I have a modal to update the profile photo of a user but when I'm trying to upload one, it gives me cors error. Tried searching, but still no luck in making it work.

The API is working fine in Postman.

This is my API that I'm fetching from the backend

enter image description here

And I'm accessing it through

const updatePhoto = (userId, token, user) => {
 return fetch(`${API}/user/photo/${userId}`, {
    method: "POST",
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json",
      Authorization: `Bearer ${token}`,
    },
    body: JSON.stringify(user),
  })
    .then((response) => {
      return response.json()
    })
    .catch((err) => {
      //console.log(err)
    })
}

This is the page I'm using when I'm trying to update the photo

const UserDetailsPage = () => {
  const classes = useStyles()

  const [userData, setUserData] = useState({
    _id: "",
    name: "",
    phone: "",
    address: "",
    birthdate: "",
    gender: "",
    messenger: "",
    photo: "",
    email: "",
  })
  const [open, setOpen] = useState(false)
  const [openPicture, setOpenPicture] = useState(false)
  const [loaded, setLoaded] = useState(false)
  const { height, width } = useWindowDimensions()
  const [picture, setPicture] = useState(null)
  const [imgData, setImgData] = useState(null)
  const [isRedirected, setIsRedirected] = useState(false)
  const [imageLink, setImageLink] = useState("")

  const {
    _id,
    name,
    phone,
    address,
    photo,
    gender,
    messenger,
    birthdate,
    email,
  } = userData

  const isMountedRef = React.useRef(false)

  useEffect(() => {
    isMountedRef.current = true
    return () => (isMountedRef.current = false)
  }, [])

  useEffect(() => {
    const user = getUser()
    // console.log(userData)

    getUserById("/user/"   user.userId, user.token)
      .then((data) => {
        if (isMountedRef.current) {
          setUserData(data)
          setLoaded(true)
        }
      })
      .catch((error) => {
        console.log(error)
      })
  }, [])

  const handleOpen = () => {
    setOpen(true)
  }

  const handleClose = () => {
    setOpen(false)
  }

  const handleOpenPicture = () => {
    setOpenPicture(true)
  }

  const handleClosePicture = () => {
    setOpenPicture(false)
  }

  const handleChangePicture = (name) => (e) => {
    setUserData({ ...userData, [name]: e.target.value })
  }

  const onChangePicture = (e) => {
    e.preventDefault()
    if (e.target.files[0]) {
      //   console.log("picture: ", e.target.files)
      setPicture(e.target.files[0])
      const reader = new FileReader()
      reader.addEventListener("load", () => {
        setImgData(reader.result)
      })
      reader.readAsDataURL(e.target.files[0])
      setImageLink(e.target.files[0].name)
    }
  }

  const clickSubmitPicture = (e) => {
    const users = getUser()
    console.log("imageLink", imageLink)
    e.preventDefault()
    console.log(userData)

    updatePicture(_id, users.token, imageLink).then((data) => {
      if (data) {
        Swal({
          text: "Your Photo has been updated",
          icon: SparkWaving,
        }).then(() => {
          setIsRedirected(true)
        })
      } else {
        Swal({
          title: "Photo updated failed.",
          text: "The server encountered an error.",
          icon: "error",
        })
      }
    })
  }

  if (isRedirected) {
    navigate("/user")
  }

  return (
    <MuiThemeProvider theme={theme}>
      <AppBar elevation={0}>
        <Toolbar>
          <Link to="/food">
            <ArrowBackIcon className={classes.backSize} />
          </Link>
        </Toolbar>
      </AppBar>
      <Toolbar />
      <div>
        <Modal
          aria-labelledby="transition-modal-title"
          aria-describedby="transition-modal-description"
          open={open}
          onClose={handleClose}
          closeAfterTransition
          BackdropComponent={Backdrop}
          BackdropProps={{
            timeout: 500,
          }}
        >
          <Fade in={open}>
            <div>
              <img
                src={photo}
                alt="User Profile"
                className={`${classes.centerFit}`}
              />
            </div>
          </Fade>
        </Modal>
      </div>
      {loaded ? (
        <>
          <div className={classes.center}>
            <label htmlFor="upload-photo">
              <div>
                <Modal
                  aria-labelledby="transition-modal-title"
                  aria-describedby="transition-modal-description"
                  open={openPicture}
                  onClose={handleClosePicture}
                  closeAfterTransition
                  BackdropComponent={Backdrop}
                  BackdropProps={{
                    timeout: 500,
                  }}
                >
                  <Fade
                    in={openPicture}
                    style={{
                      backgroundColor: "white",
                    }}
                  >
                    <Box className={classes.modal}>
                      <input
                        type="file"
                        style={{ paddingTop: "20px" }}
                        onChange={onChangePicture}
                      />

                      <div style={{ paddingTop: "1.5em" }}></div>

                      <div style={{ textAlign: "center" }}>
                        <img
                          src={imgData}
                          style={{
                            width: "100%",
                            height: "200px",
                            alignItems: "center",
                          }}
                        />
                      </div>
                      <div style={{ paddingTop: "100px" }}></div>
                      <Button
                        type="submit"
                        fullWidth
                        variant="contained"
                        className={classes.button}
                        style={{ fontFamily: "visby" }}
                        onClick={clickSubmitPicture}
                      >
                        Upload
                      </Button>
                    </Box>
                  </Fade>
                </Modal>
              </div>
              <CameraAltIcon
                onClick={handleOpenPicture}
                className={` ${classes.camera} ${classes.float} `}
              />
            </label>
            <button
              onClick={handleOpen}
              style={{ border: "0", backgroundColor: "transparent" }}
            >
              <Avatar className={classes.avatar}>
                {photo ? (
                  <img
                    src={photo}
                    className={`${classes.large} ${classes.center} ${classes.img}`}
                    onChange={handleChangePicture("photo")}
                  />
                ) : (
                  name.charAt(0)
                )}
              </Avatar>
            </button>
          </div>
        </>
      ) : (
        <div
          style={{
            display: "flex",
            height: height,
            justifyContent: "center",
            alignItems: "center",
          }}
        >
          <CircularProgress color="secondary" />
        </div>
      )}
    </MuiThemeProvider>
  )
}

export default UserDetailsPage

This is the error message

enter image description here

Am I missing something in fetching my API?

CodePudding user response:

Add this cors - NPM middleware to your backend API and also read about CORS on MDN so you understand that

CodePudding user response:

As the error states, you need to provide the correct header on the requested source to whitelist your origin.

Access-Control-Allow-Origin: <your origin>

A workaround is to provide

Access-Control-Allow-Origin: *

which whitelists all origins, however this is probably not best practice / recommended.

  • Related