【问题标题】:Accessing API Cors in React在 React 中访问 API Cors
【发布时间】:2021-11-21 02:06:09
【问题描述】:

您好,我在更新图片时遇到问题。在 Postman 中,我遇到了一个 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 时是否遗漏了什么?

【问题讨论】:

  • 你是否用 postman、curl、insomnia 或类似的东西测试过那个 API?
  • 你好,邮递员可以正常工作。
  • flutter 版本也运行良好。但在我的 React 中,因为我正在迁移。存在 cors 问题。

标签: reactjs api react-hooks


【解决方案1】:

将此 cors - NPM 中间件添加到您的后端 API 并阅读有关 CORS on MDN 的信息,以便您了解

【讨论】:

    【解决方案2】:

    如错误所述,您需要在请求的来源上提供正确的标头以将您的来源列入白名单。

    Access-Control-Allow-Origin: &lt;your origin&gt;

    解决方法是提供

    Access-Control-Allow-Origin: *

    将所有来源列入白名单,但这可能不是最佳做法/推荐。

    【讨论】:

    • 嗨,我的后端有 res.header("Access-Control-Allow-Origin", "*"); 我仍然收到 cors 问题错误。
    • 嗯,你查看过 cors 中间件吗? section.io/engineering-education/… 可能还需要启用不同的方法,但我不完全确定。
    • 是的,我尝试了很多方法。我的前端错了吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-20
    • 2020-11-28
    • 1970-01-01
    • 2023-01-14
    • 2017-02-26
    • 2019-01-04
    • 2020-02-20
    相关资源
    最近更新 更多