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 ??
Related
This has been beating me up.
I have a vuex store, inside is a folder called "RyansBag" im using to test things.
I have two other folder, Alerts and Inventory. So the folder structure for each of these goes
store> Ryansbag/Alert/...
in my Inventory index.js file, we run a function to add an item to an inventory system.
async addInventory_Catalog({commit}, payload){
try{
const response = await this.$axios.put('Inventory/AddFromCatalogDefault', null, {
params:{
originalUPC: payload.upc,
clientID: payload.clientId,
saleprice: payload.sellPrice,
cost: payload.sellPrice,
Condition: payload.condition.conditionName,
Serial: payload.serialNumber,
Notes: payload.notes,
HoldDays: payload.holdDays,
}
});
console.log(response.data.success)
commit('RyansBag/Alerts/showAlerts', 'You have added a product!', {root: true})
return response.data;
} catch (error) { alert(error); console.log(error); }
},
Here we just pass the item down, and when it's done - commit the changes to our alert which is in store > RyansBag/Alerts.
You can see I tried to call it:
commit('RyansBag/Alerts/showAlerts', 'You have added a product!', {root: true})
My understanding was to simply state the commit is coming from this store as the root state...? But Im not sure if im supposed to register the commit in /Alerts as a global item somehow. ( https://vuex.vuejs.org/guide/modules.html#accessing-global-assets-in-namespaced-modules )
EDIT:::
Edit: There was no commit request in the action. added to post. Now however I get warning to not mutate state outside of state handlers..
Below is the mutation it's requesting to reach inside the alerts.
export const mutations = {
showAlerts(state, message) {
let timeout = 0
if (state.status.showAlert) {
state.status.showAlert = false
timeout = 300
}
setTimeout(() => {
state.status.showAlert = true
state.status.message = message
}, timeout)
},
hideAlerts(state) {
state.status.showAlert = false
},
}
The fix was a) making sure I called commit in the action parameters. and b) not using setTimeout in the mutation, but instead setting a mutation to hide, and using the actions to setTime.
I encountered a problem while implementing the form where the data used in select, retrieved from the database via react-query, should only be retrieved once when clicking on input, and subsequent clicks should not cause a refetch.
How to do it in clean way?
Hook:
export const useUnitOfMeasureSelectData = ({
queryPageIndex,
queryPageSize,
queryFilters,
enabled,
refetchOnWindowFocus,
}) => {
return useQuery(
["unitofmeasure-list", queryPageIndex, queryPageSize, queryFilters],
() => fetchItemData(queryPageIndex, queryPageSize, queryFilters),
{
keepPreviousData: true,
staleTime: 60000,
enabled,
refetchOnWindowFocus,
select: (data) => {
const categories = data.data.results.map((obj) => ({
value: obj.id,
label: obj.name,
}));
return categories;
},
}
);
};
In component calling onClick={()=>refetch()} refetch data on every click.
const {
data: unitOfMeasureSelectData = [],
refetch: refetchUnitOfMeasureSelectData,
} = useUnitOfMeasureSelectData({
queryPageIndex: queryPageIndex,
queryPageSize: queryPageSize,
queryFilters: filterString,
enabled: false,
refetchOnWindowFocus: false,
});
looks like you want a lazy query with infinite stale time:
const [enabled, setEnabled] = useState(false)
useQuery(key, fn, { enabled, staleTime: Infinity })
then, when you click on the input, you call setEnabled: true. The infinite stale time makes sure that the query is always considered fresh, so no more background refetch is happening.
The button in react/native has a property disabled that you can set to false when you are done. Probably the way to do this is with state
<button disabled={this.state.btnDisable}/>
Then you can update the state when you first click the button
//class component
this.setState({btnDisable: false})
//function component
setbtnDisable(false)
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
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/')
...
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. :)