简体   繁体   English

从 Firestore 获取数据

[英]Fetching data from Firestore

So I am trying to fetch data from Firestore, when I console log it I got the content of my collection back, but when I move the code to a function I am not able to return it back.所以我试图从 Firestore 获取数据,当我控制台记录它时,我取回了我的集合的内容,但是当我将代码移动到一个函数时,我无法将其返回。

This code works:此代码有效:

const db = firebase.firestore();
db.settings({ timestampsInSnapshots: true});
db.collection('story').get().then((snapshot) => {
snapshot.docs.forEach(doc => {console.log(doc.data())
    ;})
})

This doesnt work.这不起作用。 (it compiles, but doesn`t return anything): (它编译,但不返回任何东西):

...
getMyStory = () => {
        const db = firebase.firestore();
        db.settings({ timestampsInSnapshots: true});
        db.collection('story').get().then((snapshot) => {
        snapshot.docs.forEach(doc => {
            let items = doc.data();
        })
        });
        return this.items;
    }


    render () {


        return (
        <p>{this.getMyStory}</p>
);
}

What am I doing wrong?我究竟做错了什么?

Your rendering logic will need to account for the query to Firebase being asynchronous.您的渲染逻辑需要考虑到 Firebase 的异步查询。 Consider making use of your components state to resolve this, by making the following adjustments to your code:考虑使用您的组件state来解决此问题,方法是对您的代码进行以下调整:

getMyStory() { /* Remove arrow function */

    const db = firebase.firestore();
    db.settings({ timestampsInSnapshots: true});
    db.collection('story').get().then((snapshot) => {

      snapshot.docs.forEach(doc => {
          let items = doc.data();

          /* Make data suitable for rendering */
          items = JSON.stringify(items);

          /* Update the components state with query result */
          this.setState({ items : items }) 
      });

    });
}

Next, add componentDidMount() to your component, and then add the call to getMyStory() like so:接下来,将componentDidMount()添加到您的组件,然后添加对getMyStory()的调用, getMyStory()所示:

componentDidMount() {

    /* Cause your component to request data from Firebase when
       component first mounted */
    this.getMyStory()
}

Finall, update your render method to use the state, rather than method:最后,更新您的渲染方法以使用状态,而不是方法:

  render () {

    return (<p>{ this.state.items || 'Loading' }</p>);
 }

Hope this helps!希望这可以帮助!

The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value Promise 对象表示异步操作的最终完成(或失败)及其结果值

Based in your code return this.items;基于您的代码返回 this.items; executed first and then resolve db.collection('story').get() , finally never get the results.先执行再解析db.collection('story').get() ,最后一直得不到结果。

Basically this line:基本上这一行:

db.collection('story').get()

it's a promise then you must wait that resolve the result, below code:这是一个承诺,那么你必须等待解决结果,下面的代码:

getMyStory = () => {
    const db = firebase.firestore();

    db.settings({ timestampsInSnapshots: true});

    return db.collection('story').get()
}

Read More About Promises 阅读有关承诺的更多信息

=======================EDIT========================= ========================编辑==========================

getMyStory().then((snapshot) => {
    const listItems = snapshot.map((element) =>
      <li>{element}</li>
    );

    ReactDOM.render(
      <ul>{listItems}</ul>,
      document.getElementById('root')
    );
});

Read More About Map 阅读更多关于地图

The main problem here is that you are trying to render async data synchronously, which isn't possible to do with react (not yet at least) .这里的主要问题是您正在尝试同步呈现异步数据,这与 react (至少目前还没有) 无关

When rendering async data you will usually leverage component state .渲染异步数据时,您通常会利用组件状态

Below is a standard usage pattern when loading and rendering something async.下面是加载和呈现异步内容时的标准使用模式。

class YourComponent extends Component {
  state = {
    items: []
  }

  // This method is called when the component mounts
  // Usually  a good place to do async requests
  componentDidMount() {

    db.collection('story').get().then(snapshot => {
      // After promise is finished set data to local state
      // When setting state the render method will be called, thus rerendering the UI
      this.setState({ items: snapshot })
    })
  }

  render() {
    // Access your items from local component state
    const { items } = this.state;

    return (
      <div>
        {items.forEach(doc => {
          // Render whatever data is in your document
          return <p key={doc.id}> { Your data goes here }</p>
        })
        }
      </div>
    )
  }
}
import React, { Component } from "react";
import firebase from "../config";

class App extends Component {
  constructor(props) {
    super(props);

    // Reference firebase in this.state, creating a global key-value pair
    this.state = {
      roomsRef: firebase.firestore().collection("rooms"),
      rooms: []
    };
  }

  // Retrieve data from firebase and set state
  getDb(db) {
    db.get().then(querySnapshot => {
      querySnapshot.forEach(doc => {
        let room = doc.data();
        room.key = doc.id;
        this.setState({
          rooms: this.state.rooms.concat(room)
        });
      });
    });
  }

  // 
  componentDidMount() {
    this.getDb(this.state.roomsRef);
  }

  render() {
    const rooms = this.state.rooms.map((r, i) => <li key={i}>{r.name}</li>);

    return (
      <div className="App">
        <section className="room-list">
          {this.state.rooms.length === 0 ? (
            <p>loading...</p>
          ) : (
            <ul>{rooms}</ul>
          )}
        </section>
      </div>
    );
  }
}

export default App;

if any one is using React with Redux with Firebase and has difficulty here is how to do it here i get all the publications from firestore using redux如果有人在 Firebase 中使用 React with Redux 并且遇到困难,这里是如何做到这一点我使用 redux 从 firestore 获取所有出版物

// publicationsActions.js

var publicationsRef = db.collection("publications")
var publicationsList = []

// Function that returns the publications list
export const getPublications = () => async (dispatch) => {
    await publicationsRef.get().then((res) => {
        res.docs.forEach(doc => {
            publicationsList.push(doc.data())
        })
        dispatch({
            type: GET_PUBS,
            payload: publicationsList
        })
    })
}


// publicationReducer.js

export default function (state = initialState, action) {
    switch(action.type){
        case GET_PUBS:
            return {
                ...state,
                items: action.payload
            }
        case ADD_PUB:
            return {
                ...state,
                items: [action.payload, ...state.items]
            }
        default:
            return state; 
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM