我想在点击按钮时更改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>
);
}
}
如果我添加componentWillUpdate和componentDidMount来侦听新路径,则侦听器会进入无限循环。如果我使用shouldComponentUpdate,那么最初会多次调用它,因为父组件中的其他状态正在更改,并且数据不会呈现,因为条件nextProps.path!==this.props.path
返回false
。
答案 0 :(得分: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>
你可以在componnetDidMount中弹出对它的引用,如果你想要它开始一次。
componentDidMount() {
this.funkyFirebaseFunction
}
答案 1 :(得分: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()
并将新引用发送给相应的功能。