Доступ к API-интерфейсам в React

#reactjs #api #react-hooks

Вопрос:

Здравствуйте, у меня возникли проблемы с обновлением моего изображения. В «Почтальоне» я получаю ошибку cors. У меня есть способ обновить фотографию профиля пользователя, но когда я пытаюсь загрузить ее, это выдает ошибку cors. Попробовал поискать, но все равно не получилось.

API отлично работает в Postman.

Это мой API, который я получаю из бэкэнда

введите описание изображения здесь

И я получаю доступ к нему через

 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)
    })
}
 

Это страница, которую я использую, когда пытаюсь обновить фотографию

 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
 

Это сообщение об ошибке

введите описание изображения здесь

Я что-то упускаю при получении своего API?

Комментарии:

1. Вы тестировали этот API с помощью postman, curl, insomnia или чего-то подобного?

2. здравствуйте, с почтальоном все нормально работает.

3. версия flutter также работает нормально. но в моей реакции, потому что я мигрирую. возникла проблема с cors.

Ответ №1:

Добавьте это промежуточное программное обеспечение cors — NPM в свой внутренний API, а также прочитайте о CORS в MDN, чтобы вы поняли, что

Ответ №2:

Как указано в сообщении об ошибке, вам необходимо указать правильный заголовок в запрошенном источнике, чтобы внести свой источник в белый список.

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

Обходной путь состоит в том, чтобы обеспечить

Access-Control-Allow-Origin: *

в котором перечислены все источники, однако это, вероятно, не лучшая практика / рекомендуется.

Комментарии:

1. Привет, у меня есть бэкэнд res.header("Access-Control-Allow-Origin", "*"); , я все еще получаю ошибку с проблемой cors.

2. Хм, ты заглядывал в промежуточное программное обеспечение cors? section.io/engineering-education/… Возможно, придется включить и другие методы, но я не совсем уверен.

3. Да, я перепробовал много подходов. мой интерфейс просто неправильный?