如何在我的React应用程序中链接异步Firebase更新



React&Firebase新手来了。我有一个React组件,在渲染之前需要在Firebase中查找一些内容。我的数据库设计需要首先获得正确的doohick ID,然后查找doohick详细信息,但我不确定如何使用Firebase数据库访问的异步特性来做到这一点。这不起作用:

class Widget extends React.Component {
componentDidMount() {
firebase.database().ref(`/users/${username}/doohick-ids`).on('value', snapshot => {
this.setState({doohick_ids: doohick_ids});
});
this.state.doohick_ids.forEach(id => {  
// ids don't actually exist at this point outside the callback
firebase.database().ref(`/doohick-details/${id}`).on('value', snapshot => {
// update state
});         
});
render() {
if (this.state.doohick-ids) {
return null;
} else {
// render the Doohick subcomponents
} 
}
}

我能想出一些解决方案,但没有一个是我喜欢的。建议用什么方法将Firebase调用链接在一起,或者重新设计以消除问题?

我认为应该将一个组件Widget拆分为两个WidgetListWidgetItem

WidgetItem

订阅和取消订阅firebase.database().ref(/doohick-details/${id})

class WidgetItem extends React.Component {
static propTypes = {
id: PropTypes.string.isRequired,
}
constructor(props) {
super(props);
this.state = {};
this.dbRef = null;
this.onValueChange = this.onValueChange.bind(this);
}
componentDidMount() {
const { id } = this.props;
this.dbRef = firebase.database().ref(`/doohick-details/${id}`);
this.dbRef.on('value', this.onValueChange);
}
componentWillUnmount() {
this.dbRef.off('value', this.onValueChange);
}
onValueChange(dataSnapshot) {
// update state
this.setState(dataSnapshot);
}
render() {
return (
<pre>{JSON.stringify(this.state, null, 2)}</pre>
);
}
}

小工具列表

订阅和取消订阅firebase.database().ref(/users/${username}/doohick-ids)

class WidgetItem extends React.Component {
constructor(props) {
super(props);
this.state = { doohick_ids: [] };
this.dbRef = null;
this.onValueChange = this.onValueChange.bind(this);
}
componentDidMount() {
// Note: I've just copied your example. `username` is undefined.
this.dbRef = firebase.database().ref(`/users/${username}/doohick-ids`);
this.dbRef.on('value', this.onValueChange);
}
componentWillUnmount() {
this.dbRef.off('value', this.onValueChange);
}
onValueChange(dataSnapshot) {
this.setState({ doohick_ids: dataSnapshot });
}
render() {
const { doohick_ids } = this.state;
if (doohick_ids.length === 0) {
return 'Loading...';
}
return (
<React.Fragment>
{doohick_ids.map(id => <WidgetItem key={id} id={id} />)}
</React.Fragment>
);
}
}

需要数据库数据的代码需要位于内,当数据可用时调用回调。回调之外的代码将没有正确的数据。

因此:

firebase.database().ref(`/users/${username}/doohick-ids`).on('value', snapshot => {
this.setState({doohick_ids: doohick_ids});
doohick_ids.forEach(id => {  
// ids don't actually exist at this point outside the callback
firebase.database().ref(`/doohick-details/${id}`).on('value', snapshot => {
// update state
});         
});
});

这里有很多可能的优化,但它们都可以归结为回调中的代码,并在值来自数据库时更新状态。

最新更新