Javascript 正在将图像上载到firebase存储:未经处理的拒绝(TypeError):无法读取属性';州';未定义的

Javascript 正在将图像上载到firebase存储:未经处理的拒绝(TypeError):无法读取属性';州';未定义的,javascript,reactjs,firebase,file-upload,firebase-storage,Javascript,Reactjs,Firebase,File Upload,Firebase Storage,我有一个CMS,我创建了一个标题,内容和图像的文章。然后我会在主页上显示所有这些内容。图像存储在Firebase存储中,我成功地做到了这一点(当我检查存储时,它们就在那里),但是一旦我提交表单,我就会看到以下错误: 未处理的拒绝(TypeError):无法读取未定义的属性“state” 我真的是新手,所以如果你知道哪里出了问题,请尽可能具体。我还在学习如何传递道具和所有这些 UploadFile.js import React from "react"; import fir

我有一个CMS,我创建了一个标题,内容和图像的文章。然后我会在主页上显示所有这些内容。图像存储在Firebase存储中,我成功地做到了这一点(当我检查存储时,它们就在那里),但是一旦我提交表单,我就会看到以下错误:

未处理的拒绝(TypeError):无法读取未定义的属性“state”

我真的是新手,所以如果你知道哪里出了问题,请尽可能具体。我还在学习如何传递道具和所有这些

UploadFile.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(`/articleImages/${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;
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;
import React, { Component } from "react";
import firebase from "../Firebase";
import { Link } from "react-router-dom";

class ViewAllArticles extends Component {
  constructor(props) {
    super(props);
    this.ref = firebase.firestore().collection("articles");
    this.unsubscribe = null;
    this.state = {
      articles: [],
    };
  }

  onCollectionUpdate = (querySnapshot) => {
    const articles = [];
    querySnapshot.forEach((doc) => {
      const { title, content, fileUrl } = doc.data();
      articles.push({
        key: doc.id,
        doc, // DocumentSnapshot
        title,
        content,
        fileUrl,
      });
    });
    this.setState({
      articles,
    });
  };

  componentDidMount() {
    this.unsubscribe = this.ref.onSnapshot(this.onCollectionUpdate);
  }

  render() {
    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">All articles</h3>
          </div>
          <br></br>
          <br></br>
          <br></br>
          <div className="panel-body">
            <table className="table table-stripe">
              <thead>
                <tr>
                  <th>Title</th>
                  <th>Content</th>
                  <th>Image</th>
                </tr>
              </thead>
              <tbody>
                {this.state.articles.map((article) => (
                  <tr>
                    <td>
                      <Link to={`/editArticle/${article.key}`}>
                        {article.title}
                      </Link>
                    </td>
                    <td>{article.content}</td>
                    <td>
                      <img
                        width="100"
                        height="100"
                        src={article.fileUrl}
                        onError={(e) => {
                          e.target.onerror = null;
                          e.target.src =
                            "https://images.unsplash.com/photo-1597759261513-474270ffae0f?ixlib=rb-1.2.1&auto=format&fit=crop&w=2238&q=80";
                        }}
                      />
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      </div>
    );
  }
}

export default ViewAllArticles;
从“React”导入React;
从“../firebase”导入firebase;
函数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(`/articleImages/${file.name}`)
等待fileRef.put(文件);
setFileUrl(等待fileRef.getDownloadURL()。然后(fileUrl=>{
firebase.firestore().collection('articles').doc(this.state.documentId).更新({
fileUrl:fileUrl
})
.然后(()=>{
setFileUrl(“”)
})
} ));
};
返回(
);
}
导出默认上传文件;

这是我添加UploadFile组件的表单:

AddArticle.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(`/articleImages/${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;
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;
import React, { Component } from "react";
import firebase from "../Firebase";
import { Link } from "react-router-dom";

class ViewAllArticles extends Component {
  constructor(props) {
    super(props);
    this.ref = firebase.firestore().collection("articles");
    this.unsubscribe = null;
    this.state = {
      articles: [],
    };
  }

  onCollectionUpdate = (querySnapshot) => {
    const articles = [];
    querySnapshot.forEach((doc) => {
      const { title, content, fileUrl } = doc.data();
      articles.push({
        key: doc.id,
        doc, // DocumentSnapshot
        title,
        content,
        fileUrl,
      });
    });
    this.setState({
      articles,
    });
  };

  componentDidMount() {
    this.unsubscribe = this.ref.onSnapshot(this.onCollectionUpdate);
  }

  render() {
    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">All articles</h3>
          </div>
          <br></br>
          <br></br>
          <br></br>
          <div className="panel-body">
            <table className="table table-stripe">
              <thead>
                <tr>
                  <th>Title</th>
                  <th>Content</th>
                  <th>Image</th>
                </tr>
              </thead>
              <tbody>
                {this.state.articles.map((article) => (
                  <tr>
                    <td>
                      <Link to={`/editArticle/${article.key}`}>
                        {article.title}
                      </Link>
                    </td>
                    <td>{article.content}</td>
                    <td>
                      <img
                        width="100"
                        height="100"
                        src={article.fileUrl}
                        onError={(e) => {
                          e.target.onerror = null;
                          e.target.src =
                            "https://images.unsplash.com/photo-1597759261513-474270ffae0f?ixlib=rb-1.2.1&auto=format&fit=crop&w=2238&q=80";
                        }}
                      />
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      </div>
    );
  }
}

export default ViewAllArticles;
import React,{Component}来自“React”;
从“./firebase”导入firebase;
从“./components/UploadFile”导入上传文件;
类AddArticle扩展组件{
构造函数(){
超级();
this.ref=firebase.firestore()集合(“文章”);
此.state={
标题:“,
内容:“,
文件URL:“”,
};
}
onChange=(e)=>{
const state=this.state;
状态[e.target.name]=e.target.value;
本.设置状态(状态);
};
onSubmit=(e)=>{
e、 预防默认值();
const{title,content,fileUrl}=this.state;
这个.ref
.添加({
标题
内容,,
文件URL,
})
。然后((docRef)=>{
这是我的国家({
标题:“,
内容:“,
文件URL:“”,
文档id:docRef.id,
});
this.props.history.push(“/”);
})
.catch((错误)=>{
console.error(“添加文档时出错:”,错误);
});
};
render(){
const{title,content,fileUrl}=this.state;
返回(






创建一篇新文章



标题: 内容: {content} {/* */} 提交 ); } } 导出默认的AddArticle;
最后,我有一个主页,在那里我可以显示图像和表单中的其他数据:

viewalarticles.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(`/articleImages/${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;
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;
import React, { Component } from "react";
import firebase from "../Firebase";
import { Link } from "react-router-dom";

class ViewAllArticles extends Component {
  constructor(props) {
    super(props);
    this.ref = firebase.firestore().collection("articles");
    this.unsubscribe = null;
    this.state = {
      articles: [],
    };
  }

  onCollectionUpdate = (querySnapshot) => {
    const articles = [];
    querySnapshot.forEach((doc) => {
      const { title, content, fileUrl } = doc.data();
      articles.push({
        key: doc.id,
        doc, // DocumentSnapshot
        title,
        content,
        fileUrl,
      });
    });
    this.setState({
      articles,
    });
  };

  componentDidMount() {
    this.unsubscribe = this.ref.onSnapshot(this.onCollectionUpdate);
  }

  render() {
    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">All articles</h3>
          </div>
          <br></br>
          <br></br>
          <br></br>
          <div className="panel-body">
            <table className="table table-stripe">
              <thead>
                <tr>
                  <th>Title</th>
                  <th>Content</th>
                  <th>Image</th>
                </tr>
              </thead>
              <tbody>
                {this.state.articles.map((article) => (
                  <tr>
                    <td>
                      <Link to={`/editArticle/${article.key}`}>
                        {article.title}
                      </Link>
                    </td>
                    <td>{article.content}</td>
                    <td>
                      <img
                        width="100"
                        height="100"
                        src={article.fileUrl}
                        onError={(e) => {
                          e.target.onerror = null;
                          e.target.src =
                            "https://images.unsplash.com/photo-1597759261513-474270ffae0f?ixlib=rb-1.2.1&auto=format&fit=crop&w=2238&q=80";
                        }}
                      />
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      </div>
    );
  }
}

export default ViewAllArticles;
import React,{Component}来自“React”;
从“./firebase”导入firebase;
从“react router dom”导入{Link};
类ViewAllArticles扩展组件{
建造师(道具){
超级(道具);
this.ref=firebase.firestore()集合(“文章”);
this.unsubscribe=null;
此.state={
第[…]条,
};
}
onCollectionUpdate=(querySnapshot)=>{
常量文章=[];
querySnapshot.forEach((doc)=>{
const{title,content,fileUrl}=doc.data();
推({
关键字:doc.id,
doc,//DocumentSnapshot
标题
内容,,
文件URL,
});
});
这是我的国家({
文章,,
});
};
componentDidMount(){
this.unsubscribe=this.ref.onSnapshot(this.onCollectionUpdate);
}
render(){
返回(






所有文章





标题 内容 形象 {this.state.articles.map((article)=>( {文章标题} {article.content} { e、 target.onerror=null; e、 target.src= "https://images.unsplash.com/photo-1597759261513-474270ffae0f?ixlib=rb-1.2.1&auto=格式和配合=裁剪&w=2238&q=80“; }} /> ))} ); } } 导出默认ViewAllarticle;
正如我在评论部分提到的,主要问题是在功能组件中没有
这个。状态
,只在基于类的组件中。您可以尝试通过道具将
documentId
的值从
AddArticle
组件传递到
UploadFile

解决方案可以通过
props
documentId
传递为:

<UploadFile onChange={this.onChange} value={fileUrl} documentId={this.state.documentId} />
然后,只需使用as
documentId
而不是
this.state.documentId

firebase.firestore().collection('articles').doc(documentId)

功能组件中没有此状态的
,仅在基于类的组件中。您可以尝试通过
props
documentId
的值从
AddArticle
组件传递到
UploadFile
。非常感谢您的回复!我现在得到了这个错误:如果y