javascript - React Firebase 中多个数据之间的信息
问题描述
我有一个带有管理区域的 React 应用程序,管理员用户可以在其中在一个大目录中添加一些项目。数据保存在 Firebase 中的“目录”中。
当应用程序的简单用户连接到她的帐户时,他可以查看管理员添加的项目列表,并选择将项目添加到她的收藏中(如添加到收藏功能)。她的收藏然后显示在私人页面“用户收藏”中。
我的问题是当管理员删除管理区域中的项目时,该项目也被删除到目录中,但不在用户集合中。
你可以在这里看到我的代码:
从 Firebase 到“目录页面”的数据:
class Catalogue extends React.Component {
constructor(){
super();
this.state = {
catalogue: {}
};
}
//Item from Firebase
componentDidMount() {
database.on('value', snapshot => {
this.setState({
catalogue: snapshot.val()
});
});
}
// Add item to user collection
addToCollection(key, e) {
const userUid = firebase.auth().currentUser.uid;
const collection = {
marque: this.state.catalogue[key].marque,
marquesuite: this.state.catalogue[key].marquesuite,
numero: this.state.catalogue[key].numero,
reference: this.state.catalogue[key].reference,
cote: this.state.catalogue[key].cote,
avatarURL:this.state.catalogue[key].avatarURL
};
firebase.database().ref(`users/${userUid}/collection`).child('items').ref.push(collection);
}
render(){
if(this.state.catalogue === null) {
return <p>Catalogue is empty</p>
}
const catalogue= Object.keys(this.state.catalogue).map(key => {
return (
<div className="item col-md-2" key={key}>
<img src={this.state.catalogue[key].avatarURL} height={150} with={150}/>
<h3>{this.state.catalogue[key].marque}</h3>
<h3>{this.state.catalogue[key].marquesuite}</h3>
<h4>{this.state.catalogue[key].numero}</h4>
<h4>{this.state.catalogue[key].reference}</h4>
<p>{this.state.catalogue[key].cote}</p>
<div className="text-center">
<button className="btn btn-success" onClick={this.addToCollection.bind(this, key)}>Add to my collection</button>
</div>
</div>
)
});
return (
<div class="container-fluid">
<h1 class="text-center">List of item</h1>
{catalogue}
</div>
)
}
}
const authCondition = (authUser) => !!authUser;
export default withAuthorization(authCondition)(Catalogue);
这是我的“用户收藏页面”:
class Collection extends React.Component {
constructor (props) {
super(props)
this.state = {
collection: {}
};
}
//Data from Firebase Database
componentDidMount() {
var userUid = firebase.auth().currentUser.uid;
const collection =firebase.database().ref(`/users/${userUid}/collection/items`).orderByChild('marque')
collection.on('value', snapshot => {
this.setState({
collection: snapshot.val(),
})
})
}
//Remove from user collection
removeToCollection(key, e) {
const userUid = firebase.auth().currentUser.uid;
const item = key;
firebase.database().ref(`users/${userUid}/collection/items/${item}`)
.remove();
}
renderPosts() {
this.removeToCollection = this.removeToCollection.bind(this);
return _.map(this.state.collection, (collection, key) => {
return (
<div className="item col-md-3" key={key} id={key}>
<img src={this.state.collection[key].avatarURL} height={150} with={150}/>
<h3>{collection.marque}</h3>
<h3>{collection.marquesuite}</h3>
<h4>{collection.numero}</h4>
<h4>{collection.reference}</h4>
<p>{collection.cote}</p>
<div className="text-center">
<button className="btn btn-danger" onClick={(e) => {if(window.confirm('Are you sure ?')){this.removeToCollection(key, e)};}}>Remove from my collection</button>
</div>
</div>
)
})
}
render(){
if(this.state.collection === null){
return <h2>Your collection is empty</h2>
}
return (
<div class="container-fluid">
<h1 class="text-center">Your collection</h1>
{this.renderPosts()}
</div>
)
}
}
const authCondition = (authUser) => !!authUser;
export default withAuthorization(authCondition)(Collection);
任何想法 ?
感谢您的帮助
解决方案
Firebase 实时数据库在属性之间没有引用。这意味着,虽然您作为开发人员或用户可能会看到集合中的每个项目都必须对应于目录中的项目,但 Firebase 没有内置方法来强制执行这种关系。
您可以做的是添加验证规则,以确保用户集合中的项目存在。例如,假设您保留这样的目录和用户集合:
catalogue: {
item1: { name: "Cookies" },
item2: { name: "Cookies" },
item3: { name: "Cookies" }
},
collections: {
user1: {
item1: true,
item2: true
},
user2: {
item2: true,
item3: true
}
}
您可以使用以下安全规则来确保每个规则/collections/$uid/$itemId
也必须存在于/catalogue
:
{
"rules": {
"collections": {
"$uid": {
"$itemId": {
".validate": "root.child('catalogue').child($itemId).exists()"
}
}
}
}
}
这确实意味着您只能从目录中删除一个项目,一旦用户集合中不再存在对该项目的引用。因此,对于上述示例数据,此写入将失败(因为两个用户在他们的集合中拥有该项目):
firebase.database().ref("catalogue").child("item2").remove()
但是如果我们按顺序运行下面的代码,它就会起作用:
firebase.database().ref("collections/user1/item2").remove().then(function() {
firebase.database().ref("collections/user2/item2").remove().then(function() {
firebase.database().ref("catalogue").child("item2").remove()
})
})
不过,这种代码嵌套相当笨拙,而且更新也不是原子的。这就是为什么您经常会看到这样的“级联删除”通过单个多位置更新完成:
firebase.database().ref().update({
"collections/user1/item2": null,
"collections/user2/item2": null,
"catalogue/item2": null
})
此单个语句更新数据库中的三个属性,并根据规则验证所有三个更新组合的结果是否有效(在本例中就是如此)。
推荐阅读
- vba - Outlook VBA 保存附件运行时错误 -2147287032 (80030008) 然后将其删除
- javascript - 为什么 babel 没有使用 webpack 将 es6 转换为 es5?
- android - Android Studio 4.2 不在 Gradle 栏中显示签名报告
- c++ - 我的程序如何从文本文件中读取多个单词作为一个字符串
- apache-superset - 如何在 Apache Superset 的单个仪表板上有多个与特定图表相关联的过滤器框?
- ksh - 无限循环?检查两台打印机是否在线或离线 - 如果关闭则发送电子邮件
- javascript - 旧浏览器中不支持的lookbehind的解决方法?
- python - 如何从 KSQL 表创建 KSQL 流
- sql-server - 无法调试 SQL Server Docker 容器 SSL 证书问题
- r - R安装在错误的地方