【问题标题】:How do I join the file url field (Firestore storage) with the other fields in Firestore? (react)如何将文件 url 字段(Firestore 存储)与 Firestore 中的其他字段连接起来? (反应)
【发布时间】:2020-12-15 07:12:20
【问题描述】:

我正在尝试:

  • 将图片上传到 Firebase 存储
  • 在 Firestore 中的“文章”文档下创建字段“fileUrl”
  • 引用 Firestore 中的文档,以便每张图片都知道它分配给了哪篇文章。

我设法以某种方式完成了所有这些工作,但问题是,当我提交带有标题、内容和图像的表单时,它会在 Firestore 中创建一个只有图像('fileUrl')的新文档,而不是创建包含表单其余数据的文档。

我知道这可能是因为我在 UploadFile.js 中创建了一个新文档,但是如何将 UploadFile.js 中创建的字段与 AddArticle.js 中的字段连接起来?

我还收到“未处理的拒绝(TypeError):无法读取此行的未定义的属性“状态”:

firebase.firestore().collection('articles').doc(this.state.documentId).update({
            fileUrl: fileUrl
        })

上传文件.js

import React from "react";
import firebase from '../Firebase';

function UploadFile() {

  const [fileUrl, setFileUrl] = React.useState(null);

  const onFileChange = async (e) => {
    const file = e.target.files[0]
    const storageRef = firebase.storage().ref()
    const fileRef = storageRef.child(file.name)
    await fileRef.put(file);
    setFileUrl(await fileRef.getDownloadURL().then(fileUrl => {
        firebase.firestore().collection('articles').doc(this.state.documentId).update({
            fileUrl: fileUrl
        })
        .then(() => {
            setFileUrl('')
        })
    } ));
  };

  return (
    <>
        <input type="file" onChange={onFileChange} />
      <div>
          <img width="100" height="100" src={fileUrl} alt=''/>
          
      </div>
    </>
  );
}

export default UploadFile;

AddArticle.js

import React, { Component } from 'react';
import firebase from '../Firebase';
import UploadFile from '../components/UploadFile';

class AddArticle extends Component {

  constructor() {
    super();
    this.ref = firebase.firestore().collection('articles');
    this.state = {
      title: '',
      content: '',
      fileUrl: ''
    };
  }
  onChange = (e) => {
    const state = this.state
    state[e.target.name] = e.target.value;
    this.setState(state);
  }
 
  onSubmit = (e) => {
    e.preventDefault();

    const { title, content, fileUrl } = this.state;

    this.ref.add({
      title,
      content,
      fileUrl

    }).then((docRef) => {
      this.setState({
        title: '',
        content: '',
        fileUrl: '',
        documentId: docRef.id
      });
      
      this.props.history.push("/")
    })
    .catch((error) => {
      console.error("Error adding document: ", error);
    });
  }

  render() {
    const { title, content, fileUrl } = this.state;

    return (
      <div className="container">
      <br></br><br></br><br></br>
        <div className="panel panel-default">
          <div className="panel-heading">
            <h3 className="panel-title text-center">
              Create a new article
            </h3>
          </div>
          <br></br><br></br>
          <div className="panel-body">
            <form onSubmit={this.onSubmit}>
              <div className="form-group">
                <label for="title">Title:</label>
                <input type="text" className="form-control" name="title" value={title} onChange={this.onChange} placeholder="Title" />
              </div>
              <div className="form-group">
                <label for="content">Content:</label>
                <textArea className="form-control" name="content" onChange={this.onChange} placeholder="Content" cols="80" rows="20">{content}</textArea>
              </div>
              
              {/* <input type="file" onChange={this.onFileChange} /> */}
              <UploadFile onChange={this.onChange} value={fileUrl}/>
              <button type="submit" className="btn btn-success">Submit</button>
            </form>
          </div>
        </div>
      </div>
    );
  }
}

export default AddArticle;

【问题讨论】:

  • 您的代码流程如何?哪个是顺序,是先创建文章还是上传图片?还是两个动作同时触发?
  • 嗨,我们的想法是让文本字段和上传图像采用相同的形式,并同时创建所有内容,但我无法在 AddArticle.js 中使用异步,因为 AddArticle.js是一个类,这就是为什么我将它放在不同的文件中并在文本字段下方的表单中调用组件的原因。我不确定这是否是个好主意。有没有更好的方法来做到这一点的例子?

标签: reactjs firebase file-upload google-cloud-firestore firebase-storage


【解决方案1】:

每次调用firebase.firestore().collection('articles').add(...) 时,都会向数据库中添加一个新文档。由于您在 AddArticleUploadFile 中都调用了它,因此您的图像 URL 和其他字段确实会出现在单独的文档中。

您处理文件上传的方式对我来说有点不寻常,因为我通常希望在其他字段也提交时进行上传。现在,我不清楚这张图片属于什么,正如 J.A.Hernández 也评论的那样。

无论哪种方式:您都需要删除其中一个 firebase.firestore().collection('articles').add(...) 调用,而是将文档 ID 传递给该调用。假设您首先添加文本字段并然后上传图片,UploadFile 然后可以使用以下内容更新文档:

firebase.firestore().collection('articles').doc(documentId).update({
    fileUrl: fileUrl
})

to 传递文档 ID 的一种方法是将其保持在以下状态:

this.ref.add({
  title,
  content,
  fileUrl

}).then((docRef) => {
  this.setState({
    title: '',
    content: '',
    fileUrl: '',
    documentId: docRef.id
  });
  
  this.props.history.push("/")
})

然后:

firebase.firestore().collection('articles').doc(this.state.documentId).update({
    fileUrl: fileUrl
})

【讨论】:

  • 谢谢弗兰克!我是firebase的新手,对反应不是很有经验。这个想法是让文本字段和图像具有相同的形式。我选择创建 UploadFile.js 并以这种方式单独执行的原因是因为 a)我认为将与上传相关的所有内容单独保存会更干净 b)因为 AddArticle 是一个类,我不能异步并在里面等待。有一个更好的方法吗?此外,这可能有点傻,但我把:firebase.firestore().collection('articles').doc(this.state.documentId).update({ fileUrl: fileUrl })
  • 该行将进入您现在拥有firebase.firestore().collection('articles').add(...)UploadFile 函数。
  • 我得到'未处理的拒绝(TypeError):无法读取未定义的属性'状态',我更新了上面的代码,如果你能再看看我是否误解或错过,我将不胜感激任何东西。
  • 这是我得到的 --> freeimage.host/i/d4bSdG
猜你喜欢
  • 2020-01-04
  • 1970-01-01
  • 1970-01-01
  • 2022-12-04
  • 2021-04-09
  • 2019-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多