Twitter Authentication with Vue, Vuex and Firebase - javascript

I've been trying to use a Twitter login option for a sports social media dashboard that I am trying to dissolve. I have been following this helpful tutorial I have scraped the HelloWorld component and have kept the app.vue and main.js component. Below is my code. I am receiving the error 'router not defined'. This may just be a routing issue. I have both the Twitter app and Firebase authentication correct. Any thoughts? Thanks
firebaseConfig.js
const firebaseConfig = {
apiKey: "AIzaSyBaWJ2p6TDNq1WuOVLLtjsJq1xDypaXqdM",
authDomain: "sportlydatabase.firebaseapp.com",
databaseURL: "https://sportlydatabase.firebaseio.com",
projectId: "sportlydatabase",
storageBucket: "sportlydatabase.appspot.com",
messagingSenderId: "287835560944",
appId: "1:287835560944:web:46024fe79c1d870531db35",
measurementId: "G-48VM19JE6M"
};
sign.vue
<template>
<div class="container-fluid">
<div class="row">
<div class="col-md-6">
<h3>Sign In with Twitter</h3>
<button class="btn btn-primary"
#click="signIn">
<i class="fa fa-twitter"></i>
SignIn with Twitter
</button>
</div>
</div>
</div>
</template>
<script>
export default {
methods: {
signIn () {
this.$store.dispatch('signIn')
}
}
}
</script>
<style scoped>
h3 {
font-weight: 700;
}
button {
background-color: #1dcaff;
border: 1px solid #1dcaff;
}
div button:hover {
background-color: #00aced;
border: 1px solid #00aced;
}
</style>
Home.vue
<template>
<div container-fluid>
<div>
<h2>Welcome {{ user.userDetails[0].displayName }}
</h2>
<p>You are logged in</p>
<img :src="user.userDetails[0].photoURL" alt=""
class="img-circle" height="100px" width="100px"
>
</div>
</div>
</template>
<script>
export default {
computed: {
user () {
return this.$store.getters.user
}
}
}
</script>
<style scoped>
h2 {
font-weight: 700
}
</style>
store.js
import Vue from 'vue'
import Vuex from 'vuex'
import firebase from 'firebase'
Vue.use(Vuex)
export const store = new Vuex.Store({
state: {
user: null
},
getters: {
user (state) {
return state.user
}
},
mutations: {
SET_USER (state, payload) {
state.user = payload
},
LOGOUT (state, payload) {
state.user = null
}
},
actions: {
autoSignIn({ commit }, payload) {
const newUser = {
userDetails: payload.providerData
}
commit('SET_USER', newUser)
},
signIn({ commit }) {
var provider = new firebase.auth.TwitterAuthProvider();
firebase.auth().signInWithRedirect(provider);
firebase.auth().getRedirectResult().then(result => {
// The signed-in user info.
var user = result.user;
commit('SET_USER', user)
}).catch(error => {
alert(error)
return
})
},
logout({ commit }) {
firebase.auth().signOut().then(function () {
commit('LOGOUT')
}).catch(function (error) {
alert(error)
return
});
}
}
})
index.js
router.beforeEach((to, from, next) => {
const currentUser = firebase.auth().currentUser;
const requiresAuth = to.matched.some(record => record.meta.requiresAuth);
if (requiresAuth && !currentUser) {
next('/');
}
else if (!requiresAuth && currentUser) {
next('/home');
}
else {
next();
}
});
export default router
main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue';
import App from './App';
Vue.config.productionTip = false;
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>',
});

It seems that you need to modify your main.js file as follows:
import Vue from 'vue';
import App from './App';
import router from './router'
See the main.js file from your tutorial: https://github.com/chuks-o/twitterauth/blob/master/src/main.js. Note that we do from './router' because your router index.js file is under a specific router directory.

Related

Vue 3 - State is not available and is not showing in Vue devtools

I was following a tutorial on learning Vuejs 3 and for some reason after defining my reactive object, none of the properties are available or are visible in the vue-devtools. The pokemon names I am trying to render doesn't event appear because the pokemons property is not available. Can someone help me figure out what is going on? here is my code below:
HomeView.vue:
<template>
<div class="home">
<h3>Hello World!</h3>
<p>{{number}}</p>
<ul>
<li v-for="pokemon in pokemons" :key="pokemon.name" >{{pokemon.name}}</li>
</ul>
</div>
</template>
<script>
import axios from "axios";
import { onMounted } from '#vue/runtime-core';
import { reactive } from "vue";
// # is an alias to /src
export default {
name: 'HomeView',
setup(){
let number = 1;
const state = reactive({
pokemons:[],
urlIdLookup: {}
})
onMounted( async () =>{
try {
const pokemonReq = await axios.get("https://pokeapi.co/api/v2/pokemon?");
console.log("data", pokemonReq.data);
console.log("state", state)
state.pokemons = pokemonReq.data.results;
} catch(err){
console.log(err);
}
});
}
}
</script>
App.vue:
<template>
<div class="p-14">
<router-link class="flex justify-center text-4xl text-yellow-700" to="/">Pokemon Picker</router-link>
</div>
<router-view/>
</template>
<style>
</style>
router > index.js
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about/:slug',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
}
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
export default router
You need to return your reactive data from setup function:
const { onMounted, reactive, toRefs, ref } = Vue;
const app = Vue.createApp({
setup(){
let number = ref(1);
const state = reactive({
pokemons:[],
urlIdLookup: {}
})
onMounted( async () =>{
try {
const pokemonReq = await axios.get("https://pokeapi.co/api/v2/pokemon?");
state.pokemons = pokemonReq.data.results;
} catch(err){
console.log(err);
}
});
return { ...toRefs(state), number }
}
})
app.mount('#demo')
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.27.2/axios.min.js" integrity="sha512-odNmoc1XJy5x1TMVMdC7EMs3IVdItLPlCeL5vSUPN2llYKMJ2eByTTAIiiuqLg+GdNr9hF6z81p27DArRFKT7A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div id="demo">
<div class="home">
<h3>Hello World!</h3>
<p>{{number}}</p>
<ul>
<li v-for="pokemon in pokemons" :key="pokemon.name" >{{pokemon.name}}</li>
</ul>
</div>
</div>

"TypeError: Cannot read property 'push' of undefined" Vuejs

I am using Vue Cli but giving this error! I am trying to Register and then move to Index page. But router is not working here.
In main.js I used router for NProgress, here it is working but why not in this case??
main.js
import Vue from 'vue'
import VueRouter from 'vue-router';
Vue.use(VueRouter);
import router from './Router/routes.js'
import User from './Helpers/User'
window.User = User
new Vue({
render: h => h(App),
router,
}).$mount('#app')
User.js
import Axios from "axios";
class User {
register(data) {
let uri = 'http://localhost:8000/api/auth/register';
let self = this;
Axios.post(uri, data).then((res) => {
self.$router.push({name:'Index'})
}).catch( (error) => {
console.log(error);
});
}
}
export default User = new User();
Register.vue
<template>
<div class="col-md-12">
<div class="card card-container">
<form name="form" #submit.prevent="handleRegister">
----
</form>
</div>
</template>
<script>
export default {
data() { return { user: {} }},
methods: {
handleRegister() {
this.registration();
});
},
registration() {
User.register(this.user);
}
},
}
</script>
routes.js
import components are okay. I also import Vue and VueRouter here.
const routes = [
//
];
const router = new VueRouter({
routes
})
export default router
What is the problem here?? router is working in main.js
Giving me error in this line:
self.$router.push({name:'Index'})
Vue-Router will not work in custom js file file like User.js
Use it in Vue Component. Like:
Register.vue
<template>
<div class="col-md-12">
<div class="card card-container">
<form name="form" #submit.prevent="handleRegister">
----
</form>
</div>
</template>
<script>
export default {
data() { return { user: {} }},
methods: {
handleRegister() {
this.registration();
});
},
registration() {
User.register(this.user);
this.$router.push({ name: 'Index'});
}
},
}
</script>
The other answer is correct but what the case of the registration failure !, so try to add a callback as parameter then call it inside then :
class User {
register(data,cb) {
let uri = 'http://localhost:8000/api/auth/register';
let self = this;
Axios.post(uri, data).then((res) => {
cb()
}).catch( (error) => {
console.log(error);
});
}
}
registration() {
User.register(this.user, ()=>{this.$router.push({ name: 'Index'});});
}

React Native app doesn't connect with Firebase anymore

I am facing an issue for the last 2 weeks. I was able to connect successfully my React Native app to Firebase and could see the details on the Firebase console. However, 2 weeks back the app suddenly stopped working. All I see now is a white screen. I am trying to capture Facebook Login through Firebase and tried removing firebase code and was successfully able to connect with the FB(So I guess the issue is with Firebase connection).
Any pointers will be highly appreciated.
Here is my code
App.js
import React from 'react';
import Login from './screens/Login';
import reducers from './redux/reducers';
import thunkMiddleware from 'redux-thunk';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
const middleware = applyMiddleware(thunkMiddleware)
const store = createStore(reducers, middleware);
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<Login/>
</Provider>
);
}
}
Login Screen
import React from 'react';
import styles from '../styles'
import NavigationContainer from '../navigation/RootNavigator';
import { connect } from 'react-redux';
import { login } from '../redux/actions'
import * as firebase from 'firebase';
import firebaseConfig from '../config/firebase.js'
import * as Facebook from 'expo-facebook';
firebase.initializeApp(firebaseConfig);
import {
Text,
View,
Alert,
TouchableOpacity
} from 'react-native';
class Login extends React.Component {
state = {}
UNSAFE_componentWillMount() {
firebase.auth().onAuthStateChanged((user) => {
if (user != null) {
this.props.dispatch(login(true))
console.log("We are authenticated now!" + JSON.stringify(user));
}
});
}
login = async () => {
try {
await Facebook.initializeAsync({
appId: '1742056282625463',
});
const {
type,
token,
} = await Facebook.logInWithReadPermissionsAsync({
permissions: ['public_profile'],
});
if (type === 'success') {
// Get the user's name using Facebook's Graph API
const response = await fetch(`https://graph.facebook.com/me?access_token=${token}`);
Alert.alert('Logged in!', `Hi ${(await response.json()).name}!`);
// Build Firebase credential with the Facebook access token.
const credential = await firebase.auth.FacebookAuthProvider.credential(token);
// Sign in with credential from the Facebook user.
firebase.auth().signInWithCredential(credential).catch((error) => {
// Handle Errors here.
Alert.alert("Try Again")
});
} else {
// type === 'cancel'
Alert.alert("Cancel")
}
} catch ({ message }) {
alert(`Facebook Login Error: ${message}`);
}
}
render() {
if(this.props.loggedIn){
return (
<NavigationContainer/>
)
} else {
return (
<View style={styles.container}>
<TouchableOpacity onPress={this.login.bind(this)}>
<Text>{this.props.loggedIn}</Text>
</TouchableOpacity>
</View>
)
}
}
}
function mapStateToProps(state) {
return {
loggedIn: state.loggedIn
};
}
export default connect(mapStateToProps)(Login);
Firebase
var firebaseConfig = {
apiKey: "AIzaSyCWjS5WxFgaBajsWKQPFLbC9QekmyxiO7I",
authDomain: "bookworm-d8e9f.firebaseapp.com",
databaseURL: "https://bookworm-d8e9f.firebaseio.com",
projectId: "bookworm-d8e9f",
storageBucket: "bookworm-d8e9f.appspot.com",
messagingSenderId: "1097080341399",
appId: "1:1097080341399:web:767ce9b106a13ae103bad2",
measurementId: "G-2JY9B79XCC"
};
// Initialize Firebase
//firebase.initializeApp(firebaseConfig);
//firebase.analytics();
module.exports = firebaseConfig
Redux - Action
export function login(input){
return function(dispatch){
dispatch({ type: 'LOGIN', payload: input });
}
}
Redux - Reducers
export default reducers = (state = {
loggedIn: false,
}, action) => {
switch (action.type) {
case 'LOGIN': {
return { ...state, loggedIn: action.payload }
}
}
return state;
}

vueX with vuei18n. this.dispatch is not able to access vuei18n

I am relatively new to Vue and I've been reading the documentation and forums for quite a while for a solution to this one but haven't found it yet.
I am using the Vue Webpack template: here
I'm trying to create an app where I have an API endpoint to get the currency and country for the user as well as the user language from the browser.
I am using this.$store.dispatch('setlanguage') on initialisation of the Vue Component to set the state of the language, and save it to a cookie. The problem here though is that I am unable to alter the vuei18n as my app says it does not exist. The reason I am using vuei18n instead of vueXi18n is because the latter does not have the numberFormat options and this is needed in order to set correctly the currency symbols.
So to get things started:
Project structure:
main.js
App.Vue
store
getters.js
index.js
mutation-types.js
mutations.js
router
index.js
lang
locales
en.js
fr.js
de.js
lang.js
components
LocaleSwitcher.vue
pages
Footer.vue
Home.vue
main.js
import Vue from 'vue'
import VueResource from 'vue-resource'
import Cookies from 'js-cookie'
import App from './App.vue'
import i18n from './lang/lang'
import store from './store'
import router from './router'
Vue.use(VueResource)
Vue.config.productionTip = false
Vue.config.language = Cookies.get('lang')
Vue.config.country = Cookies.get('country')
Vue.config.currency = Cookies.get('cur')
export const localeStrings = {
en: 'English',
de: 'Deutsch',
fr: 'Français',
it: 'Italiano',
nl: 'Nederlands',
sv: 'Svenska',
es: 'Español',
ja: '日本語'
}
export const app = new Vue({
el: '#app',
router,
store,
i18n: i18n,
render: h => h(App),
created () {
this.$store.dispatch('setLang', Vue.config.language)
this.$store.dispatch('setCountry', Vue.config.country)
}
})
lang.js
import Vue from 'vue'
import VueI18n from 'vue-i18n'
Vue.use(VueI18n)
let i18n = new VueI18n({
locale: 'en',
messages: {},
fallbackLocale: 'en',
numberFormats: {}
})
export default {i18n}
App.vue
template>
<div id="app">
<app-header></app-header>
<div class="main-content">
<router-view></router-view>
</div>
<app-footer></app-footer>
</div>
</template>
<script>
export default {
name: 'myapp',
components: {
'app-footer': Footer
},
data () {
return {
msg: 'Welcome to Your Vue.js App',
language: ''
}
}
}
<style>
body {
margin:0;
padding:0;
}
</style>
Home.vue
<template>
<h1>Hello Home! {{msg}}</h1>
</template>
<script>
export default {
data () {
return {
msg: 'Home msg'
}
}
}
</script>
<style scoped>
h1 {
font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
}
</style>
Footer.vue
<template>
<footer>
<p>{{copyright}}</p>
<local-switcher></local-switcher>
</footer>
</template>
<script>
import LocaleSwitcher from '../components/LocaleSwitcher.vue'
export default {
name: 'Footer',
components: {
'local-switcher': LocaleSwitcher
},
data () {
return {
copyright: 'Copyright 2018 Francesco'
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
footer{
background: lightgrey;
padding: 10px;
}
</style>
LocaleSwitcher.vue
<template>
<div class="locale-switcher">
<select v-model="activeLocale" #change="changeLang">
<option v-for="(lang, id) in locales" :key="id" v-bind:value="id">{{lang}}</option>
</select>
</div>
</template>
<script>
import {localeStrings} from '../main'
export default {
name: 'locale-switcher',
data: function () {
return {
activeLocale: this.$store.getters.getLanguage,
locales: localeStrings
}
},
methods: {
changeLang () {
this.setLang(this.activeLocale)
},
setLang (lang) {
this.$store.dispatch('setLang', lang)
}
}
}
</script>
router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import p404 from '../pages/error/404.vue'
import Home from '../pages/Home.vue'
Vue.use(Router)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '*',
name: '404',
component: p404
}
]
let router = new Router({
mode: 'history',
routes
})
// I still have to figure out how to use this to set www.mypage.com/mylanguage/home
// use beforeEach route guard to set the language
router.beforeEach((to, from, next) => {
// use the language from the routing param or default language
let language = to.params.lang
console.log(language)
console.log('router end')
if (!language) {
language = 'en'
}
// set the current language for vuex-i18n. note that translation data
// for the language might need to be loaded first
// Vue.i18n.set(language)
next()
})
export default router
store/getters.js
export const getters = {
getLanguage: state => {
return state.language
},
getCountry: state => {
return state.country
},
getCurrency: state => {
return state.currency
}
}
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import { state, mutations, actions } from './mutations'
import { getters } from './getters'
Vue.use(Vuex)
// const mapState = Vuex.mapState
const store = new Vuex.Store({
state,
mutations,
actions,
getters
})
export default store
store/mutation-types.js
export const SET_LANG = 'SET_LANG'
export const SET_COUNTRY = 'SET_COUNTRY'
export const SET_CURRENCY = 'SET_CURRENCY'
store/mutations.js
import Vue from 'vue'
import Cookies from 'js-cookie'
import * as types from './mutation-types'
import {app, supportedLocale, supportedCurrencies} from '../main'
import CountryCurrency from '../data/country_currency.json'
import locale2 from 'locale2'
export const state = {
language: Cookies.get(settings.languageCookie),
country: Cookies.get(settings.countryCookie),
currency: Cookies.get(settings.currencyCookie),
loading: false
}
export const mutations = {
[types.SET_LANG] (state, payload) {
Cookies.set('lang', payload)
state.language = payload
},
[types.SET_COUNTRY] (state, payload) {
Cookies.set('country', payload)
state.country = payload
},
[types.SET_CURRENCY] (state, payload) {
Cookies.set('currency', payload)
state.currency = payload
}
}
export const actions = {
async setLang ({commit}, language) {
console.log(app)
console.log(Vue)
var vueMessages = app.$i18n.messages
var userLocale = 'en'
var browserLocale = locale2.split('-', 1)[0]
// testing browser language
if (locale === undefined) {
// get browser language
userLocale = browserLocale
} else if (browserLocale !== locale) {
console.log('browser language changed')
userLocale = browserLocale
} else {
userLocale = locale
}
// check for supported languages
if (!supportedLocale.includes(userLocale)) {
userLocale = 'en'
}
if (language in vueMessages) {
console.log('already in messages')
commit(types.SET_LANG, language)
} else if (!supportedLocale.includes(language)) {
console.log('not supported so commiting default en')
commit(types.SET_LANG, 'en')
} else {
try {
// you can use fetch or import which ever you want.
// Just make sure your webpack support import syntax
// const res = await axios.get(`./src/lang/${payload}.json`)
const res = await import(`../lang/locales/${language}.json`)
app.$i18n.locale = language
app.$i18n.setLocaleMessage(language, res)
var addNumberFormats = {
currency: {
style: 'currency', currencyDisplay: 'symbol', currency: `${app.$i18n.currency}`
}
}
app.$i18n.mergeNumberFormat(language, addNumberFormats)
Cookies.set('lang', language)
commit(types.SET_LANG, language)
} catch (e) {
console.log(e)
}
}
},
setCountry ({commit}, countryCode) {
var userCountry = 'NA'
if (countryCode === undefined || countryCode === 'NA') {
Vue.http.get('https://www.myapi.com/api/v2/geo/country-code', {
timeout: 100
}).then(response => {
state.country = response.data.code
Cookies.set('country', response.data.code)
}, response => {
// error callback
state.country = userCountry
Cookies.set('country', userCountry)
})
} else {
console.log(countryCode)
state.country = countryCode
Cookies.set('country', countryCode)
}
},
setCurrency ({commit}, countryCode) {
var userCurrency = 'USD'
console.log('user country ' + countryCode)
console.log('user currency ' + CountryCurrency[countryCode])
console.log('currency supported: ' + supportedCurrencies.includes(CountryCurrency[countryCode]))
if (CountryCurrency[countryCode] && supportedCurrencies.includes(CountryCurrency[countryCode])) {
userCurrency = CountryCurrency[countryCode]
}
Cookies.set('currency', userCurrency)
app.$i18n.currency = userCurrency
try {
var addNumberFormats = {
currency: {
style: 'currency', currencyDisplay: 'symbol', currency: `${app.$i18n.currency}`
}
}
if (!app.$i18n.numberFormats[app.$i18n.locale]) {
console.log('merge currency')
app.$i18n.setNumberFormat(app.$i18n.locale, addNumberFormats)
}
} catch (error) {
console.log(error)
}
}
}
The problem is that once loaded, I cannot access the app vue i18n. Am I accessing it incorrectly or is there another way to add language and currency settings to this? I hope I have provided enough info Thanks!
Could this answer be relevant in your case? https://stackoverflow.com/a/45460729/2964531
If you need to access or mutate properties of i18n, you can import it directly from store/mutations.js

store is not defined vue.js

I have created login page. router intercepting the request and validates the user is authenticated or not . store is maintaining the user is logged in or not.
while debugging i am getting in auth.js
"store is not defined"
I also tried relative path instead of # in imports.
router code snippet
import auth from '#/services/auth';
...
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
if (!auth.loggedIn()) {
next({
path: '/login',
});
} else {
next();
}
} else {
next();
}
});
auth.js is like service which will interact with store and maintain state .
import Vue from 'vue';
import axios from 'axios';
import VueAxios from 'vue-axios';
import store from '#/store/UserStore';
Vue.use(VueAxios, axios);
export default {
login(credentials) {
return new Promise((resolve, reject) => {
Vue.axios.post('/api/authenticate', credentials).then((response) => {
localStorage.setItem('token', response.body.token);
store.commit('LOGIN_USER');
resolve();
}).catch((error) => {
store.commit('LOGOUT_USER');
reject(error);
});
});
},
isUserLoggedIn() {
return store.isUserLoggedIn();
},
};
here is my store to
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
strict: process.env.NODE_ENV !== 'production',
state: {
isLogged: !localStorage.getItem('token'),
user: {},
},
actions: {
},
mutations: {
/* eslint-disable no-param-reassign */
LOGIN_USER(state) {
state.isLogged = true;
},
/* eslint-disable no-param-reassign */
LOGOUT_USER(state) {
state.isLogged = false;
},
},
getters: {
isUserLoggedIn: state => state.isLogged,
},
modules: {
},
});
change export type in UserStore like this:
line
export default new Vuex.Store({
replace with
export const store = new Vuex.Store({

Categories

Resources