从Firestore获取数据

3

我正在尝试从Firestore获取数据,当我控制台记录它时,我得到了我的集合内容,但是当我将代码移到一个函数中时,我无法将其返回。

这段代码可以工作:

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

这段代码不能正常工作(虽然它可以编译,但是没有返回任何值):

...
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>
);
}

我做错了什么?
5个回答

10

您的呈现逻辑需要考虑到 Firebase 查询是异步的。请考虑利用组件的 state 来解决此问题,通过对您的代码进行以下调整:

您的渲染逻辑需要考虑到 Firebase 查询是异步的。请考虑使用组件的 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 }) 
      });

    });
}

接下来,在您的组件中添加componentDidMount(),然后像这样添加调用getMyStory()


componentDidMount() {

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

最后,更新你的渲染方法以使用状态而不是方法:

  render () {

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

希望这有所帮助!


我也尝试过了。仍然没有返回任何东西。 - Gabi C
不行。:( 它会显示“加载”几秒钟,然后显示“对象无效作为React子元素(找到具有键{story}的对象)。如果您想呈现一组子元素,请改用数组。” - Gabi C
@DacreDenny,由于它将JSON对象转换为字符串,因此在显示时如何引用检索到的对象的特定字段。例如items.location。这是不可能的,因为我们使用JSON.stringify()函数将纯字符串存储在状态中。 - Anil
@DacreDenny,问题已解决。可以使用JSON.parse()来解决。如果我有错,请纠正我。 - Anil

1

Promise对象代表异步操作的最终完成(或失败)及其结果值。

根据你的代码,return this.items;先执行,然后是resolve db.collection('story').get(),最终无法获取结果。

基本上就是这行代码:

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

这是一个 Promise,你必须等待它解决结果,以下是代码:

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

    db.settings({ timestampsInSnapshots: true});

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

了解更多有关Promise的内容

=======================编辑=========================

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

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

阅读更多有关地图的内容


同样的问题也出现在这里。:/ “对象不是有效的React子元素(找到:[object Promise])。如果您想呈现一组子元素,请改用数组。” - Gabi C
@GabriellaCsernus,请查看我的答案!希望能帮到你。 - ene_salinas
代码只是一个想法,在问题仍然存在的情况下,请发布所有代码以获取更多建议。 - ene_salinas

1
主要问题在于你试图同步地呈现异步数据,这在react中是不可能做到的(至少目前为止)
在呈现异步数据时,通常会利用组件状态state
下面是加载和呈现异步内容的标准使用模式。
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>
    )
  }
}

0

如果有人正在使用React和Redux以及Firebase,并且遇到了困难,这是如何解决的。 在这里,我使用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; 
    }
}

0
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;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接