我有一个ReactJS/Redux/Saga应用程序,它目前从Firebase实时数据库发送和读取数据。发送和接收数据时,有一个全局 redux 状态值loading
,该值在发送数据和确认数据现在位于 Firebase 之间true
和false
之间切换。 对于这种情况,loading
默认为 false
。
当用户更新其数据时,流当前为:
- Redux reducer
SEND_TO_FIREBASE
return { ...state, loading: true };
- 此化简器触发 Saga 函数
sendToFirebaseSaga()
function* syncToFirebaseSaga({ payload: userData }) {
try {
var uid = firebase.auth().currentUser.uid;
const database = (path, payload) => {
firebase
.database()
.ref(path)
.set(payload);
};
yield call(database, "users/" + uid + "/userData", userData);
yield console.log("successfully written to database");
} catch (error) {
alert(error);
}
}
- 所以,在这一点上
loading:true
(确认这是有效的( - 然后,作为我的根组件之一
componentDidMount
的一部分,我有一个侦听器来更改 Firebase 数据库:
var props = this.props
function updateStateData(payload, props) {
props.syncFirebaseToState(payload);
}
function syncWithFirebase(uid, props) {
var syncStateWithFirebaseListener = firebase.database().ref("users/" + uid + "/userData");
syncStateWithFirebaseListener.on("value", function(snapshot) {
var localState = snapshot.val();
updateStateData(localState, props);
});
}
this.props.syncFirebaseToState(payload)
是使用此化简器的 Redux 操作:
return { ...state, data: action.payload, loading: false };
- 然后确认数据已写入 Firebase 实时数据库,然后关闭加载页面,让用户知道他们的更新现在是安全的。
在大多数情况下,此流程工作正常。但是,当用户的互联网连接不良或刷新页面太快时,我会遇到问题。例如:
- 用户加载应用。
- 断开与互联网的连接。
- 提交数据。
- 完整循环立即工作并
loading:false
(Firebase 实时数据库将其写入"离线模式",正在等待重新连接到互联网( - 用户重新联机连接。
- 上线后,用户立即刷新页面(重新加载 React 应用程序(
- Firebase 实时数据库没有时间将排队的更新同步到远程数据库,现在页面刷新后,编辑不会进行。
有时,用户不必失去互联网连接。如果他们提交编辑(页面立即返回"成功读取"(,然后在远程服务器写下之前刷新,则刷新完成后数据将丢失。
无论如何,正如你所看到的,这是一个非常糟糕的用户体验。在删除加载屏幕之前,我真的需要一种方法来确认数据是否已实际写入Firebase。我觉得我一定在这里做错了什么,并且不知何故得到了成功的回调。
这是我第一次使用 React/Redux/Saga/Firebase,所以我感谢你的耐心和帮助!
您可以禁用离线模式。
我假设您不想这样做,因此接下来是添加一个条件来检查您的更新是来自缓存还是数据库。
Firebase 实时数据库在/.info/connected
处提供了一个特殊位置,每当 Firebase 实时数据库客户端的连接状态发生变化时,该位置都会更新。下面是一个示例:
var connectedRef = firebase.database().ref(".info/connected");
connectedRef.on("value", function(snap) {
if (snap.val() === true) {
alert("connected");
} else {
alert("not connected");
}
});
然后,可以在更新的同时运行此检查以关闭加载,然后根据更改是来自缓存还是实际数据库传播更改。