React:动态更改Firebase路径

问题描述 投票:1回答:2

我想在按钮点击时更改firebase路径。旧连接断开连接但未建立新连接。下面是我正在使用的代码实例。

import React, { Component } from "react";
import firebase from "./firebase";

class ParentComponent extends Component {
  constructor() {
    super();
    this.state = {
      path: "someDirectory1/subDirectory"
    };
    this.changePath = this.changePath.bind(this);
  }

  changePath() {
    this.setState({ path: "/someDirectory2/subDirectory" });
  }

  render() {
    return (
      <React.Fragment>
        <ChildComponent path={this.state.path} />
        <button onClick={this.changePath}>Change path</button>
      </React.Fragment>
    );
  }
}

class ChildComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      mountRef: firebase.database().ref(this.props.path + "/path2")
    };
  }

  componentWillMount() {
    var ref = firebase.database().ref(this.props.path + "/path1");
    ref.once("value", snapshot => {
      var data = snapshot.val();
      //Some functionality
    });
  }

  componentDidMount() {
    var ref = this.state.mountReference;
    ref.on("value", snapshot => {
      var snapshotData = snapshot.val();
      //some functionality
    });
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.path !== this.props.path) {
      this.state.mountReference.off("value");
      var ref = firebase.database().ref(nextProps.path);
      this.setState({ path: nextProps.path, ref });
    }
  }

  render() {
    return (
      <React.Fragment>
        {/* {Some rendering} */}
        {/* {Some rendering} */}
      </React.Fragment>
    );
  }
}

如果我添加componentWillUpdatecomponentDidMount来收听新路径,那么监听器就会进入无限循环。如果我使用shouldComponentUpdate,那么它最初会被调用多次,因为其他状态在父组件中被更改,而数据不会呈现,因为条件nextProps.path!==this.props.path返回false

javascript reactjs firebase firebase-realtime-database
2个回答
0
投票

由于您希望在Click上更改路径,因此您应远离生命周期方法,并将您的逻辑放入一个单击时触发的函数。如果您希望在组件安装时触发一次该函数,则在componentDidMount中调用它。

例如:

funkyFirebaseFunction() {
 firebase.database()
  .ref(this.props.path + "someDirectory1/subDirectory")
  .once("value", snapshot => {
      var data = snapshot.val();
      //Some functionality
    });
}

然后你可以在函数内重复firebase调用,并在boolean in状态的基础上在两者之间交替。

this.state = {
  clicked: false
}

只需确保在firebase调用后翻转布尔值。

funkyFirebaseFunction() {
  this.state.clicked ?
     firebase.database()
      .ref(this.props.path + "someDirectory1/subDirectory")
      .once("value", snapshot => {
          var data = snapshot.val();
          //Some functionality
        })
     : firebase.database()
      .ref(this.props.path + "someDirectory2/subDirectory")
      .once("value", snapshot => {
          var data = snapshot.val();
          //Some functionality
        });

     this.setState({clicked: !this.state.clicked});

    }

然后调用onClick函数

<button onClick={() => this.funkyFirebaseFunction()}>Change path</button>

您可以在componentDidMount中弹出对它的引用,如果您希望它一开始就触发一次。

componentDidMount() {
  this.funkyFirebaseFunction
}

0
投票

我找到了多路径的解决方案。

import React, { Component } from "react";
import firebase from "./firebase";

class ChildComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      mountRef: firebase.database().ref(this.props.path + "/path2")
    };
    this.oneTimeListen = this.oneTimeListen.bind(this);
    this.asyncListen = this.asyncListen.bind(this);
  }



  componentWillMount() {
    var ref = firebase.database().ref(this.state.path + "/path1");
    this.oneTimeListen(this.props.path, ref);
  }

  componentDidMount() {
    var ref = this.state.mountReference;
    this.asyncListen(ref);
  }



  componentWillReceiveProps(nextProps) {
    if (nextProps.path !== this.props.path) {
      this.state.mountReference.off("value");

      // initial listen
      var ref = firebase.database().ref(nextProps.path + "/path1");
      this.setState({ path: nextProps.path });
      this.oneTimeListen(nextProps.path, ref);

      // listens to changes
      ref = firebase.database().ref(nextProps.path + "/path2");
      this.asyncListen(ref, true);
    }
  }

  /**
   * Listens to path only for one time initially.
   * @param {String} path - firebase path
   * @param {Object} ref - firebase reference variable
   */
  oneTimeListen(path, ref) {
    ref.once("value", snapshot => {
      var data = snapshot.val();
      //functionality
  }


  /**
   * Listens continuously to changed values
   * @param {Object} ref - firebase reference variable
   * @param {Boolean} setNewRef - if true, change this.state.mountReference, (only true, when firebase path changes)
   */

  asyncListen(ref, setNewRef) {
    ref.on("value", snapshot => {
      var snapshotData = snapshot.val();
      //functionality

      if (setNewRef) {
         this.setState({ mountReference: ref });
      }
    });
  }

  render() {
    return (
      <React.Fragment>
        {/* {Some rendering} */}
        {/* {Some rendering} */}
      </React.Fragment>
    );
  }
}

oneTimeListen()用于初次听path1

asyncListen()用于在path2上持续收听。

每当收到新路径时,componentWillReceiveProps()会调用oneTimeListen()asyncListen()并将新引用发送给相应的函数。

© www.soinside.com 2019 - 2024. All rights reserved.