首页 > 解决方案 > Firebase Firestore 只写了第一次尝试新版本

问题描述

我一直在用 Firebase 和 React Native 构建一个应用程序,主要是使用 Firestore。我开始使用 Firestore,它很棒,但由于某种原因,在写入 Firestore 时,它​​只在第一次尝试时起作用(当我删除应用程序、重建并执行我的写入时)。

除了写入 Firestore 之外,我尝试做完全相同的事情,并且一切都按预期工作。

我也没有收到错误!

这是我正在做的事情:

export const addBrandProduct = (postObj) => {
  return () => {
    firebase
      .firestore()
      .collection('brandProducts')
      .add(postObj)
      .then((docRef) => {
        console.log("Document written with ID: ", docRef.id);
        Actions.categories();
      })
      .catch(error => {
        console.error("Error adding document: ", error);
      });
  };
};

有关更多参考,这是我调用 addBrandProduct() 的组件代码

  onUploadImages = () => {
    let photo =
      Platform.OS === 'ios'
        ? this.state.images.map(img => img.uri.replace('file://', ''))
        : this.state.images.map(img => img.uri);

      photo.forEach((image, i) => {
      const sessionId = new Date().getTime();
      const Blob = RNFetchBlob.polyfill.Blob;
      const fs = RNFetchBlob.fs;
      window.XMLHttpRequest = RNFetchBlob.polyfill.XMLHttpRequest;
      window.Blob = Blob;
      let uploadBlob = null;
      let mime = 'image/jpg';
      const imageRef = firebase
        .storage()
        .ref('brandProducts/')
        .child(`${this.props.userData.uid}`)
        .child(`${sessionId}-${i}`);

      fs.readFile(image, 'base64')
        .then(data => {
          return Blob.build(data, {type: `${mime};BASE64`});
        })
        .then(blob => {
          uploadBlob = blob;
          return imageRef.put(blob, {contentType: mime});
        })
        .then(() => {
          uploadBlob.close();
          return imageRef.getDownloadURL();
        })
        .then(url => {
          //if this is the last uploaded image, post data to db
          if (i === this.state.images.length - 1) {
            const urls = {
              ...this.state.urls,
              [i]: url,
            };
            const postObj = {
              ...this.state.postObj,
              urls: urls,
            };
            this.props.addBrandProduct(postObj);
          } else {
            this.setState({
              urls: {
                ...this.state.urls,
                [i]: url,
              },
            });
          }
        })
        .catch(error => {
          console.log(error);
        });
    });
  };

基本上,我最多上传 3 张图片以及一些数据。为了确保在添加帖子数据(写入firestore)之前上传它们,我使用了forEach,在最后一次上传时,当它完成时,我正在调用写入帖子数据的操作。

标签: javascriptfirebasereact-nativegoogle-cloud-firestore

解决方案


HumaddBrandProduct是一个创建另一个函数的函数。因此,当您调用this.props.addBrandProduct(postObj)任何内容都不会发送到 Firestore 时,您只需创建一个应该调用的新函数。

也许你可以把这些东西拿出来直接调用firebase,确保一切正常,如果你仍然想使用它,然后再回到redux方式。我也让它并行化而不是顺序化。希望它有所帮助,当它可能来自任何地方时,很难找到真正的问题。

onUploadImages = () => {
    let photo = Platform.OS === 'ios'
    ? this.state.images.map(img => img.uri.replace('file://', ''))
    : this.state.images.map(img => img.uri);

    Promise.all( photo.map( image => {
        const sessionId = new Date().getTime();
        const Blob = RNFetchBlob.polyfill.Blob;
        //This is kind useless
        //const fs = RNFetchBlob.fs;
        //This is not used
        //window.XMLHttpRequest = RNFetchBlob.polyfill.XMLHttpRequest;
        //This is not adviced
        //window.Blob = Blob;
        let uploadBlob = null;
        let mime = 'image/jpg';

        const imageRef = firebase
        .storage()
        .ref('brandProducts/')
        .child(`${this.props.userData.uid}`)
        .child(`${sessionId}-${i}`);

        return fs.readFile(image, 'base64')
        .then(data => {
            return RNFetchBlob.polyfill.Blob.build(data, {type: `${mime};BASE64`});
        })
        .then(blob => {
            uploadBlob = blob;
            return imageRef.put(blob, {contentType: mime});
        })
        .then(() => {
            uploadBlob.close();
            return imageRef.getDownloadURL();
        });
    ))
    .then( results => {
        //results is, here, [ urlFromFirst, urlFronSecond, ...]
        const urls = { ...this.state.urls};
        results.forEach( (r, i) => urls[i] = r );
        const postObj = {
            ...this.state.postObj,
            urls
        };
        
        return firebase
        .firestore()
        .collection('brandProducts')
        .add(postObj)
    })
    .then( docRef => {
        console.log("Document written with ID: ", docRef.id);
    })
    .catch(error => {
        console.error(error);
    });
};

推荐阅读