在Redux中保存实时侦听器

时间:2019-03-29 16:40:36

标签: reactjs firebase redux

我需要在登录时触发firestore实时侦听器,以侦听用户个人资料数据的更改,并在注销前将其取消。为此,我需要将实时侦听器保存在卡住的商店中。我正在尝试在Redux中做到这一点

export const cancelListener = (cancelListener) => {
return {
    type: actionTypes.CANCEL_LISTENER,
    cancelListener: cancelListener
}
}

export const uDataListener = (uid) => {
return dispatch => {
    dispatch(uDataStart())
    const dbRef = db.collection("user").doc(uid)
    const cancelSubscription = dbRef
        .onSnapshot(
            (doc) => {
                dispatch(uDataSuccess(doc.data()))
            }
            , ((error) => {
                dispatch(uDataFail(error.message))})
        );
    dispatch(cancelListener(cancelSubscription))
}
}

注销后,只需从redux商店中调用

export const logout = (cancelListener) => {
cancelListener()
fire.auth().signOut()
return {
    type: actionTypes.AUTH_LOGOUT
}
}

但是什么都没有保存在cancelListener中,因此无法触发它。我如何完成这项任务?请 谢谢

2 个答案:

答案 0 :(得分:0)

简短地思考一下,在uDataListener中调用一个动作,例如START_LISTENER,在reducer中,您可以:

    import { store } from './yourStore';

    let cancelListener, dbRef;
    function reducer(state, action) {
     switch (action.type) {
        case "START_LISTENER":
          dbRef = db.collection("user").doc(action.uid)
          cancelSubscription = dbRef.onSnapshot(function(doc) {
            store.dispatch( 
              yourAction(doc.data()); //Dispatch new action using store
            )
          })
          return state;
        case "STOP_LISTENER":
          cancelListener()
          return state;
        default:
          return state;
    }

STOP_LISTENER将在您注销时分派

下面您将看到链接如何从组件外部调度 Update React component by dispatching action from non-react component

答案 1 :(得分:0)

我在半夜醒来时有了其他主意。我试图将方法添加到运行中的常量中,而不是将方法保存在redux状态或reducer中。我不确定这是否是最好的方法,但确实可以。现在,我只是不明白为什么我没有首先尝试这种方法。这是需要一些调整的代码,但是它可以工作

let cancelListener = null

export const logout = () => {
cancelListener()
fire.auth().signOut()
return {
    type: actionTypes.AUTH_LOGOUT
}
}

export const auth = (email, password) => {
return dispatch => {
    dispatch(authStart())
    fire.auth().signInWithEmailAndPassword(email, password).then((u) => {
        dispatch(authSuccess(u.user))
        const dbRef = db.collection("user").doc(u.user.uid)
        cancelListener = dbRef.onSnapshot((doc) => {
            dispatch(saveUserData(doc.data()))
        })
    }).catch((error) => {
        dispatch(authFailed(error.message))
    });

}
}

无论如何,非常感谢您的帮助。我真的很感激