首页 > 解决方案 > 如何在 firebase 实时数据库上找到特定路径,然后使用文本输入更改该路径的值?

问题描述

流行测验,能手:

您正在构建一个反应原生应用程序。您将一些值设置为 firebase 作为应用程序根目录中的对象,如下所示:

firebase
      .database()
      .ref("/companies/")
      .set({
        awesomeCompany: {
          name: "Awesome Company",
          owner: "Joe Awesome",
          gmail: "joeawesome@gmail.com",
          fleetSize: 2
        },
        badCompany: {
          name: "Bad Company",
          owner: "Joe Bad",
          gmail: "joebad@gmail.com",
          fleetSize: 3
        }

您想为当前用户提供一个文本输入字段,如果他们是该公司的所有者,他们可以通过该字段更改该公司的舰队大小。

您的 Firebase 身份验证工作正常,因此您知道这firebase.auth().currentUser.email将有助于检查以确定他们是否是所有者。

您的数据库值已设置 - 它们如下所示:

{
  "companies": {
    "awesomeCompany": {
      "fleetSize": 2,
      "gmail": "joeawesome@gmail.com",
      "name": "Awesome Company",
      "owner": "Joe Awesome"
    },
    "badCompany": {
      "fleetSize": 3,
      "gmail": "joebad@gmail.com",
      "name": "Bad Company",
      "owner": "Joe Bad"
    }
  }
}

您将如何将初始信息呈现到屏幕上,以及如何设置文本输入逻辑以便用户输入更改数据库中的数据?

为了了解我的大脑,以及我是如何失败的,我在下面包含了我自己的代码作为起点。如果有办法向我展示如何采用我的基本策略并使其发挥作用——即使它并不优雅——我将不胜感激。但总的来说,我真的很纠结如何使用 Data Snapshot 获取数据路径引用并让它们可以在其他地方使用。

感谢您的帮助,任何人!

// my crummy half baked code below
import React, { Component } from "react";
import { View, Text, TextInput, Button } from "react-native";
import { styles } from "../styles";
import * as firebase from "firebase";

export default class OwnerProfileScreen extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      gmail: null,
      name: null,
      fleetSize: null
    };
  }

  componentDidMount() {
    this.getData();
  }

  getData = () => {
    const rootRef = firebase.database().ref(); // firebase reference
    const authEmail = firebase.auth().currentUser.email; // current user

    return rootRef.once("value").then(
      function(snapshot) {
        const idArray = Object.keys(snapshot.child("companies/").val()); // array of Ids

        const companyData = idArray.map(id =>
          snapshot.child("companies/" + id).val()
        ); //  values of contained in objects at each key

        const ownersCompany = companyData.filter(
          obj => obj.gmail === authEmail
        ); // an array containing one object if the gmail address in the object is the same as the currentUser logged in


           // what is the path of fleetSize?  
           // how do I define it to keep it available to use later 
           // with a Text Input event?

        this.setState({
          name: ownersCompany[0].name,
          gmail: ownersCompany[0].gmail,
          fleetSize: ownersCompany[0].fleetSize
        });
      }.bind(this)
    );
  };

  changeFleetSize = userInput => {
    //in order to set the user input to the database, I need the path
    //of the fleetSize of the current user (who has been verified as an 
    // owner by comparing firebase auth to gmail addresses of company)
  };

  render() {
    return (
      <View style={styles.container}>
        <Text>minPrice = {this.state.name}</Text>
        <Text>gmail = {this.state.gmail}</Text>
        <Text>fleetSize = {this.state.fleetSize}</Text>
        <TextInput
          style={{ height: 40, borderColor: "gray", borderWidth: 1 }}
          //onChangeText currently does nothing since I don't know how
          // to get the particular path of particular fleetSize 
          onChangeText={userInput => this.changeFleetSize(userInput)} 
        />
      </View>
    );
  }
}

标签: javascriptreact-nativefirebase-realtime-database

解决方案


代码非常混乱,因此很难说出您要完成的工作。但让我在这里猜测一下:

  1. 你想从你的数据库中加载一个公司。
  2. 您知道公司所有者的电子邮件地址。

如果这是正确的,您可以使用查询来完成目标。就像是:

var query = rootRef.child("companies").orderByChild("gmail").equalTo(authEmail);
var self = this;
query.once("value").then(function(result) {
  result.forEach(function(snapshot) { // loop over result snapshots, since there may be multiple
    const companyData = snapshot.val();

    self.setState({
      name: companyData.name,
      gmail: companyData.gmail,
      fleetSize: companyData.fleetSize
    });
  })
);

这里的变化:

  1. 使用查询仅选择具有正确 gmail 地址的公司。
  2. 循环遍历结果,因为(至少在 API 级别上)可能有多家公司对其gmail财产具有该价值。
  3. 摆脱整个迭代Object.keys和过滤,因为这使得它难以阅读。对于 Firebase 实时数据库代码,此结果也更惯用。
  4. 用于self跟踪this实例,只是因为我不想计算bind调用次数。

推荐阅读