首页 > 解决方案 > 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);

任何想法 ?

感谢您的帮助

标签: javascriptreactjsfirebasefirebase-realtime-database

解决方案


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

此单个语句更新数据库中的三个属性,并根据规则验证所有三个更新组合的结果是否有效(在本例中就是如此)。


推荐阅读