【问题标题】:React: How can I show an already existing image in react update form and then show the new one once a new image is uploaded?React:如何在 React 更新表单中显示已经存在的图像,然后在上传新图像后显示新图像?
【发布时间】:2021-02-17 05:54:57
【问题描述】:

大家好,我正在学习 react js,我有一个更新表格来更新书籍信息。我正在使用 django rest api 作为端点。我有一个工作表单,我可以上传文件并做所有这些事情,但我无法显示模板中已经存在的图像,这里我有一个书籍封面图像,它已经存在于数据库中,它应该显示在前端,当我更改图像时,应该显示新图像,我如何在此处添加该功能,我尝试了<img src={formData.book_cover} 并安慰这是显示 url,但图像没有显示.

在网络选项卡中, 我认为的问题是

Request URL:http://localhost:3000/media/book/book_sample/pride_in_nat.png

请求 url,因为如果 url 是 localhost:8000 而不是 localhost:3000 则显示图像,因为它是 django 服务器后端运行的地方。那么,我该如何改变呢?

这是代码。

import React from "react";

function BookInfoForm() {

  const initialFormData = Object.freeze({
  id: '',
  book_cover: '',
  book_name: '',
  book_summary: '',
});

const [formData, updateFormData] = useState(initialFormData);
const [image, setImage] = useState(null);
const { register, handleSubmit, control, errors } = useForm();

useEffect(() => {
  axiosInstance.get('api/books/info/update/').then((res) => {
    updateFormData({
              ...formData,
      ['book_cover']: res.data.book_cover,
      ['book_name']: res.data.book_name,
      ['book_summary']: res.data.book_summary,
    });
  });
  }, [updateFormData]);

  const handleChange = (e) => {
    if (e.target.name === 'image') {
        setImage({
            image: e.target.files,
        });
        // console.log(e.target.files);
    } 
    updateFormData({
        ...formData,         
  // Trimming any whitespace
      [e.target.name]: e.target.value
    });
};

const onSubmit = (data) =>{
  let formData = new FormData();

  formData.append('user', user.id),
  formData.append('book_cover', data.image[0]),
  formData.append('book_name', data.book_name),
  formData.append('book_summary', data.book_summary),

  axiosInstance.put('api/books/info/update/', formData),
}

return (
  <>
    <form className={classes.form} noValidate onSubmit={handleSubmit(onSubmit)}>
      <Grid container spacing={2}>
            <Grid item xs={6}>
                {/* Show existing book cover and change when new one is uploaded */}
                <img src={formData.store_logo} alt="" />
                <label htmlFor="book-cover">
                    <input
                    accept="image/*"
                    className={classes.input}
                    id="book-cover"
                    onChange={handleChange}
                    name="image"
                    type="file"
                    ref={register}
                />
                    Book Cover
                    <IconButton color="primary" component="span">
                        <PhotoCamera />
                    </IconButton>
                </label>
            </Grid>

            <Grid item xs={12}>
                <TextField
                    variant="outlined"
                    required
                    fullWidth
                    id="book_name"
                    label="Book Name"
                    name="book_name"
                    autoComplete="book_name"
                    value={formData.book_name}
                    onChange={handleChange}
                    inputRef={register({maxLength: 30})}
                    rows={1}
                />
            </Grid>

            <Grid item xs={12}>
                <TextField
                    variant="outlined"
                    required
                    fullWidth
                    id="book_summary"
                    label="Book Summary"
                    name="book_summary"
                    autoComplete="book_summary"
                    value={formData.book_summary}
                    onChange={handleChange}
                    inputRef={register({maxLength: 1000})}
                    multiline
                    rows={3}
                />
            </Grid>
          </Grid>

          <Button
            type="submit"
            fullWidth
            variant="contained"
            color="primary"
            className={classes.submit}
          >
            Update
        </Button>

      </form>
  </>
)
}

【问题讨论】:

  • 关于您的图片请求的网络标签显示了什么?
  • 嘿,感谢您的回复,我检查了网络选项卡并显示了文件,但是当我单击时,它显示一个空白页面。我认为的问题是Request URL: http://localhost:3000/media/book/book_sample/pride_in_nat.png,如图所示,如果 url 是 localhost:8000,因为它是 django 服务器后端运行的地方。那么,如何改变呢?
  • 您将 URL 的哪一部分存储在数据库中?是http://localhost:3000/media/book/book_sample/pride_in_nat.png 还是pride_in_nat.png 还是别的什么?
  • 对不起,我没听懂这个问题。我没有对其正常的保存行为进行任何更改,
  • 在数据库中链接是book/book_sample/pride_in_nat.png

标签: javascript reactjs react-native react-router jsx


【解决方案1】:

您可能想看看我在Why React needs webpack-dev-server to run? 上的回答之一

由于您的前端在localhost:3000 运行并且您提供了img 标记的相对路径,因此浏览器假定图像位于localhost:3000

当您的后端主机与前端主机不同时,您必须提供资源的完整 URL,即 origin(http://localhost:8000) + 资源路径(/book/book_sample/pride_in_nat.png)

当您在数据库中存储资源路径时,只需将 origin 附加到 img 标记即可。

<img src={`http://localhost:8000/${formData.store_logo}`} />

建议

更好的方法是使用.env 文件并根据您的developmentproduction 环境加载它们

<img src={`${process.env.IMAGE_STORE_ORIGIN}${formData.store_logo}`} />

在您的.env 文件或.env.development 文件中,您可以添加图片存储位置的条目

在您的.env 文件中:

IMAGE_STORE_ORIGIN=http://localhost:8000/

因此,当您想要更改后端服务器来源时,您只需在一个位置进行更改,它就会在您的整个应用程序中使用,而不是每次您想使用新的服务器地址时都手动更改。

看看dotenvdotenv-expand

我希望这能澄清你的“为什么”和“什么”。

【讨论】:

  • 感谢您的精彩解释和给出的答案,我对.env 文件有疑问。我应该在公共或 src 文件夹中创建此文件吗?
  • @Danny 它应该出现在你的项目目录的根目录下,即你的package.json 所在的位置。
  • 哦。但我没有,我有 3 个文件 package.jsonpackage-lock.jsongitignore。我错过了什么吗?
  • @Danny 建议部分只是生产级项目中常用的一种模式。您无需创建 .env 文件即可使其立即为您工作。您可以按照建议上方的部分使其工作
  • 哦。好的谢谢你!它现在起作用了。再次感谢您的解释和时间。 :)
【解决方案2】:

我认为这是最好的解决方案,即使我没有大量使用 Django,我也会强烈推荐它。

我知道使用 Django,您可以将文件存储在 settings.py 中配置的媒体文件中,我猜这既方便又方便,但据我所知,管理文件的最佳解决方案是处理像 cloudinary 这样的第 3 方(在使用第 3 方软件管理文件的 Node 时非常常见)

那么后面的流程:

  • 在 cloudinary 上创建一个帐户(不用担心它完全免费,但可以升级)
  • 当您想将文件保存到 DB 时,您首先需要使用 Django 与 cloudinary 进行交互。
  • 一旦 Django 完成,cloudinary Api 将带回您的图片的网址。
  • 那么您现在只需将给定的链接保存在您的数据库中

现在使用您的 Django 模型

  • 在您将 image 作为“FileField”的地方,现在您可以安全地转换为“CharField”或任何在 django 中忘记的文本/字符串
  • 那么现在在你的 React 应用中应该可以工作了

适用于 Django 的 Cloudinary SDK 文档

https://cloudinary.com/documentation/django_integration

如果文档不清楚,您也可以在 YouTube 上查找一些示例

https://youtu.be/1T6G7Znrbfg

【讨论】:

  • 感谢您的建议,但我希望在这里解决和学习我遇到的这个问题。当然,也会尝试用 coloudinary 来做到这一点。感谢您的信息。
猜你喜欢
  • 1970-01-01
  • 2021-11-28
  • 1970-01-01
  • 2014-02-16
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 2020-06-24
  • 1970-01-01
相关资源
最近更新 更多