Let's add Firebase to our Vue + Vuex App with no nonsense.
Tip: Ctrl + F for "recipe" to find variables to update
NPM
npm i firebase core-js
Config Files
Add src/firebase.js
:
import * as firebase from "firebase/app";
import "firebase/auth";
import "firebase/firestore";
// π This example is using Auth + Firestore
var firebaseConfig = {
// This comes from Google - add your config here
};
firebase.initializeApp(firebaseConfig);
// utils
const db = firebase.firestore();
const auth = firebase.auth();
// collections
const usersCollection = db.collection("users");
const recipeCollection = db.collection("recipe");
// π Here you create your Collections you want to use later
// π You export things here | update the variable names
export { db, auth, usersCollection, recipeCollection };
Modify src/main.js
// π Add this to your imports
import { auth } from "./firebase";
// π Wrap your new Vue like this
let app;
auth.onAuthStateChanged(user => {
if (!app) {
app = new Vue({
router,
store,
render: h => h(App)
}).$mount("#app");
}
if (user) {
store.dispatch("fetchUserProfile", user);
}
});
Vuex Store
Template State
// π Add these imports
import * as firebase from "../firebase";
import router from "../router/index";
// π Add this outside your store const if it isn't user dependent filtering
firebase.recipeCollection
// π Replace this with your variable from firebase.js
.where("public", "==", true)
// π This filters incoming data
.onSnapshot(snapshot => {
let recipeArray = [];
snapshot.forEach(doc => {
let recipe = doc.data();
recipe.id = doc.id;
recipeArray.push(recipe);
});
// π Create an array of all docs found.
store.commit("setRecipes", recipeArray);
});
// π From here down replaces the export default new Vuex.Store({...}) that Vue adds by default
const store = new Vuex.Store({
state: {
userProfile: {},
recipes: []
},
mutations: {
setUserProfile(state, val) {
state.userProfile = val;
},
setRecipes(state, val) {
state.recipes = val;
}
},
actions: {
async login({ dispatch }, form) {
const {
user
} = await firebase.auth.signInWithEmailAndPassword(
form.email,
form.password
);
dispatch("fetchUserProfile", user);
},
async fetchUserProfile({ commit }, user) {
const userProfile = await firebase.usersCollection
.doc(user.uid)
.get();
commit("setUserProfile", userProfile.data());
if (router.currentRoute.path === "/login") {
router.push("/");
}
},
async logout({ commit }) {
await firebase.auth.signOut();
// clear userProfile and redirect to /login
commit("setUserProfile", {});
router.push("/login");
},
async createRecipe({ state, commit }, recipe) {
let now = new Date();
// π Model your record here
await firebase.recipeCollection.add({
createdOn: now,
userId: firebase.auth.currentUser.uid,
username: state.userProfile.name,
});
},
async signup({ dispatch }, form) {
// sign user up
const {
user
} = await firebase.auth.createUserWithEmailAndPassword(
form.email,
form.password
);
// π Add this to your login form as the submit function
// login() {
// this.$store.dispatch("login", {
// email: this.loginForm.email,
// password: this.loginForm.password
// });
// },
// create user profile object in userCollection
await firebase.usersCollection.doc(user.uid).set({
name: form.name
});
dispatch("fetchUserProfile", user);
},
}
});
export default store;
V-Router
// π Add this to your imports
import { auth } from "../firebase";
// ...
// π An example route that requires user to be authenticated
const routes = [
{
path: "/",
name: "Home",
component: Home,
meta: {
requiresAuth: true
}
},
]
// ...
// π Add this just before your export
router.beforeEach((to, from, next) => {
const requiresAuth = to.matched.some(
x => x.meta.requiresAuth
);
if (requiresAuth && !auth.currentUser) {
// π Direct the user to this path if not logged in
next("/login");
} else {
next();
}
});
References
These sources helped me get this working the first time:
Top comments (0)