5
votes

I have the following setup in my vuex store: My users log in with Firebase authentication. Upon login, firebase.auth().onAuthStateChanged is called and user is set to state.user but also saved in the Firebase database. The moment when I add the last part of my code (database.ref...) my console explodes with errors. The errors, however, are not related to Firebase but to Vuex.

Errors are the following (x80):

[Vue warn]: Error in callback for watcher "function () { return this._data.$$state }":

Error: [vuex] Do not mutate vuex store state outside mutation handlers.

My code still works, but during development, I don't want to see 80 errors as the user logs in. How can I get rid of these errors?

// actions
const actions = {
  startListeningToAuth ({ commit }) {
    firebase.auth().onAuthStateChanged((user) => {
      commit(types.SET_USER, { user })
    })
  }
}

// mutations
const mutations = {
  [types.SET_USER] (state, { user }) {
    state.user = user

    if (user) {
      database.ref('users/' + user.uid).set({
        name: user.displayName,
        email: user.email,
        photo_url: user.photoURL
      })
    }
  }
}
3

3 Answers

5
votes

You can use toJSON() method to the firebase.User interface

commit(types.SET_USER, { user.toJSON() })

This will allow to add user data to your store without warnings but i guess that you can lose the realtime user state from firebase.

See https://firebase.google.com/docs/reference/js/firebase.User#toJSON

0
votes

Mutations should only contain code that directly affects the vuex state.

You are getting the errors because database.ref() is most likely modifying the user object in some way. In your mutation, state.user = user makes it so that your state.user object is referencing the same object as your user variable. So, if user changes outside of the mutation, the state will also change, and Vue will yell at you.

You should move your database.ref() call to the related action method and then commit the mutation. Since database.ref() is async, you need to wait for that method to finish before committing the mutation:

// actions
const actions = {
  startListeningToAuth ({ commit }) {
    firebase.auth().onAuthStateChanged((user) => {
      if (user) {
        database.ref('users/' + user.uid).set({
          name: user.displayName,
          email: user.email,
          photo_url: user.photoURL
        }).then(() => {
          commit(types.SET_USER, { user })
        })
      }
    })
  }
}

// mutations
const mutations = {
  [types.SET_USER] (state, { user }) {
    state.user = user
  }
}
0
votes

Did you want set user data after register? this is my code to do this

firebase.auth().createUserWithEmailAndPassword(email, password)
                .then((user) => {
                    //init user
                    userRef.child(user.uid).set({
                        email: email,
                        //Other data 
                    });
                })
                .catch((error) => {
                    state.isRegenter code hereister = false;
                    console.log(error);
});