firebase.auth().onAuthStateChanged getting null after refresh page in vuex - javascript

i am using Vuex and Firebase Authentication. I got stuck when reload the page. firebase.auth().onAuthStateChanged take time to response. But i need at the same time when reload the page. I have seen many tutorials in internet, most of them is router guard, but that i don’t want. I have some route where the user has login, then can navigate to this route.
App.vue where i am applying.
created () {
firebase.auth().onAuthStateChanged(async user =>{
if (user){
await this.$store.dispatch('autoSignIn',user)
}
})
}
Here is my vuex action theat trigger when page reload to auto sign in if a user was logged before reload the page.
autoSignIn ({commit}, payload) {
commit('setUser',{email:payload.email, userId:payload.uid})
}
This is my getter
isAuthenticated:state => {
return state.user !== null && state.user !== undefined ? state.user : null
}
Here is where i am calling my getter isAuthenticated.
getEventsByUser({getters,commit}){
let data = [];
firebase.database().ref('usuario/' + getters.isAuthenticated.userId + '/eventos/')
.on("value", eventos =>{
eventos.forEach(evento =>{
data.push({"id":evento.key, ...evento.val()})
});
commit('setEventsByUser',data)
})
},
And this is the component which dispatch the action
<template>
<div>
<div v-for="(event,id) in getEventsByUser" :key="id">
{{event}}
</div>
</div>
</template>
<script>
export default {
name: "MyEvents",
computed:{
getEventsByUser(){
return this.$store.getters.getEventsByUser;
},
},
mounted() {
this.$store.dispatch('getEventsByUser')
},
}
Here is the error when i reload the page

When the page loads, Firebase checks whether the ID token that is stored for the user is still valid. This requires that it calls the server, so it may take a moment. During this check the user will be null, so your code needs to handle that everywhere.
In your onAuthStateChanged handler you handle this correctly with:
firebase.auth().onAuthStateChanged(async user =>{
if (user){
But then in getEventsByUser you assume there is a user, which (as shown by the error message) is not true. So you'll want to add a check there, to see if there's a user, before attaching the listener to the database:
getEventsByUser({getters,commit}){
let data = [];
if (getters.isAuthenticated) {
firebase.database().ref('usuario/' + getters.isAuthenticated.userId + '/eventos/')
...

Related

Showing modal on successfully posting data from redux

Hey guys i am using React Hooks with redux, so what i want is lets say user need a signup on my website, so after posting his details i am sending back status :200 and if it has status:200 i am updating a state value in my userReducer like say "status" to true (which initially was false) and based on this boolean value i am showing a modal to user with the message. So code goes like
Actions.js
export const userRegisterAction = (data: any) => async (dispatch: any) => {
console.log(data);
axios.post("http://localhost:4000/register_user", data).then((res) => {
console.log("hittinh server");
console.log(res.data);
if (res.data.status == 200) {
dispatch({
type: USER_REGISTRATION_SUCCESS,
payload: res.data,
});
} else {
dispatch(errorActions());
}
});
};
Reducer.js
case USER_REGISTRATION_SUCCESS:
return {
...state,
status: true,
info: action.payload.doc.ops[0],
};
and then in my component
const user = useSelector((state: RootState) => {
console.log(state.user.info);
console.log(state.error.iserror);
return { user: state.user };
});
<IonAlert
isOpen={user.user.status == true}
cssClass="my-custom-class"
header={"User Registered!"}
backdropDismiss={false}
// subHeader={'User Registered !'}
message={"You have been registered successfully."}
// buttons={["OK"]}
buttons={[
{
text: "OK",
handler: () => {
console.log("Confirm Okay");
redirect();
},
},
]}
/>
Note. I am using redux persist and this reducer needs to be persisted for future purpose as i am gonna use this wherever i need user related task like if he needs to change password i will pick up the email from my user reducer so it doesnt gets lost on refresh
NOW COMING TO THE ISSUE, as my reducer state is persisted once the "status" is true if user wishes to signup from another account as soon as he goes to signup page he will again see the result of "ionAlert" as it will match the condition status==true , so what i am doing is on every unmount i am dispatching action which sets "status" to false, although this works fine, but i wanna know is this the correct approach , how are you all dealing with this stuff ??

Vuex problems, important project, MapActions,MapGetters

The reason why I am writing here because I just got a job as a front-end developer and on the first day they threw at me a big project and I lost, very lost, hopeless.
My job would be that I am having a home page where there is a table with some information for example date, hours, the daily wind speed, daily celsius, and under the table there would be information which can be generated from a config panel.
So basically with Vue-router am having two pages, one with the home and one with the config panel, now in the config panel I am having a form where you can write your text you want to display to the home page and my problem is that I have no clue how to display that text from one router to another I tried to make a method where on submitting the form it should somehow commit that message to my Vuex state but when I am about to write it out to the home page it is now showing,
This is what I have in my modules (vuex file) :
const state = {
message: '',
};
const getters = {
message: (state) => {
return state.message;
},
};
const actions = {
setMessage: ({
commit,
state
}, newValue) => {
commit('SET_MESSAGE', newValue);
return state.message;
},
};
const mutations = {
SET_MESSAGE: (state, newValue) => {
state.message = newValue;
console.log(state.message);
},
};
export default {
state,
getters,
actions,
mutations,
};
when I am console logging the state.message the text which got submitted is there now I need to put this text to my homepage, please help me with that I know that this should be an easy one but I cannot solve it.
On home page you should add
created() {
this.$store.dispatch('SET_MESSAGE');
}
This code will call SET_MESSAGE
computed: {
...mapGetters({
message: 'message',
}),
}
After adding this part you can take message value simple call "this.message" in methods or "message" in template

reset the star-rating component, VUE JS

I am using star-rating plugin in vue js, and I am using v-model to show the ratings from db. Everything works fine as when user is not logged in and he/she tries to rate it shows an error "login to rate", but the stars dont reset to db value instead it shows the rating of not logged in user. Currently after the error msg I am refreshing the whole page. Is there a simple way to reset the stars instead of refreshing the whole page?
:show-rating="false" #rating-selected="setRating" v-model="rating"
v-bind:star-size="20"
above is the start rating and while clicking it calls a function where I am checking if user is logged in or not with an api call. Thanks in advance.
setRating: function (rating) {
axios.get('/checkuser').then(response => {
this.user = response.data;
if (this.user === "Logout") {
toastr.error('Please login to rate', 'Error', {
positionClass: 'toast-bottom-right'
});
window.location = "/menu/" + this.menu_id;
} else {
// save in to db
}
}).catch(error => {
// TODO: Handle error
});
},
You will have to reset rating object if it's not logged in.
setRating: function (rating) {
axios.get('/checkuser').then(response => {
...
if (this.user === "Logout") {
...
this.rating = 0; <=== reset rating here (in data, not the rating parameter)
}
...
})
...
},
managed to fix it by using "this.load()" after the api call, which refreshes all components. :)

How can i use localStorage to maintain state after a page refresh in React

Each time a user logs in, i want the state to remain at 'true' even if there is a page reload.
The state is set initially to false, (let _authed = false).
But when i reload the page, it goes back to false, which is the index page.
What i did
When the user logs in, i save the user's details in localStorage and when the user logs out, i cleared the localStorage and i set it to false. (this works fine)
In the setAuthed() function, i tried to check if the user i stored in localStorage is not null, it should keep the authed variable to true.
But its not working when i refresh the page. Is there anything, i am doing wrong? Help appreciated.
let _authed = false;
// User logs in, set user in localStorage
saveUser(user){
_user = user;
localStorage.setItem('user', JSON.stringify(user))
},
//User clicks logout, set state to false
setLogout(){
_authed = false;
localStorage.clear()
},
// If there is a user in local storage, always set state to true
setAuthed(){
if (localStorage.getItem("user") !== null) {
_authed = true;
}
},
getAuthed(){
return _authed;
},
You can use React lifecycle methods to read and write some kind of persistent state. Here I've wrote a tiny example to show it.
class Root extends React.Component {
state = {
isLoggedIn: false
}
componentDidMount () {
const persistState = localStorage.getItem('rootState');
if (persistState) {
try {
this.setState(JSON.parse(persistState));
} catch (e) {
// is not json
}
}
}
componentWillUnmount () {
localStorage.setItem('rootState', JSON.stringify(this.state);
}
render () {
return (
<div>
{this.props.children}
</div>
)
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Vue.js - using v-on:click and v-link together

I'm developing a Vue.js app and I'm trying to make a log in system using multiple components.
on my App.vue component (which is the "primary" component and has the nav-bar) there is this button:
<a class="nav-item" v-link="'login'" v-if="!user.authenticated">Login</a>
...
import auth from '../auth'
export default {
data(){
return{
user = auth.user
}
}
}
In one other file (/auth/index.js) I define the "auth" methods as such:
...
user: {
authenticated: false
},
login(email, password) {
axios.post(LOGIN_URL, {
email,
password
}).then((response) => {
this.user.authenticated = true;
this.user = response.data;
router.go('/home');
})
.catch((error)=>{
console.log(error);
});
}
And then I have another component name Login.vue that handles the view for the login template and calls the "auth.login" method with the required params.
The thing is that I want to update the user from App.vue with the value from auth.user AFTER he logs in. How should I do that? Do I have to manage the v-on:click and v-link priorities and come up with a new method?
EDIT:
I'm also trying to use the beforeRouteEnter method by I am not being successful
I managed to find a solution adding this:
watch: {
$route () {
this.user = auth.user
}
},
Following the documentation here

Categories

Resources