因此,我尝试从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>
);
}
我在做什么错了?
答案 0 :(得分:3)
您的呈现逻辑将需要考虑对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()
}
Finall,更新渲染方法以使用状态,而不是方法:
render () {
return (<p>{ this.state.items || 'Loading' }</p>);
}
希望这会有所帮助!
答案 1 :(得分:1)
Promise对象代表最终的完成(或失败) 异步操作及其结果值
根据您的代码首先返回this.items; ,然后解析 db.collection('story')。get(),最后再也没有得到结果。
基本上此行:
db.collection('story').get()
这是一个承诺,然后您必须等待下面的代码来解决结果:
getMyStory = () => {
const db = firebase.firestore();
db.settings({ timestampsInSnapshots: true});
return db.collection('story').get()
}
================================================= ==
getMyStory().then((snapshot) => {
const listItems = snapshot.map((element) =>
<li>{element}</li>
);
ReactDOM.render(
<ul>{listItems}</ul>,
document.getElementById('root')
);
});
答案 2 :(得分:1)
这里的主要问题是您试图同步呈现异步数据,而这与react (not yet at least)无关。
呈现异步数据时,通常将利用组件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>
)
}
}
答案 3 :(得分: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;
答案 4 :(得分: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;
}
}