I have a state in the Vuex store that reacts to the change in the button and everything changes its dependent value, the problem is that I am using it in a component and I call it in the data()
data() {
return {
currency: this.$store.state.currency,
}
}
When mounting the component, everything is displayed fine, because it takes the value from storage, but when I update that value, the change is not reflected in the component.
I would like to know how I could make the variable render again with the new value of the storage, every time it changes.
I tried using the currency variable where I save the data, it did not work and I also tried to place the variable directly where it is used, but it did not work either
computed: {
currency() {
return this.$store.state.currency;
},
},
Do it like that.
Related
I have two components in mu app.vue and i will send data from app.vue to my first component(filter component) at the time of page load.
Now based on the user actions in the displayed data in the second component i need to pass new vales back to the first component.
There i am using a and a . Consider one of the props i receive in the first component is "nselectedOption" and i do this in data: { return { selectedOption: this.nselectedOption }} to avoid mutation warning.
Now everytime i update the values for this component from second component, i am seeing changes in "nselectedOption" only and not in "selectedOption". Can you explain why is that ?
I need the updated value into a v-model of .
1. If i use "nselectedOption" it is updating the textbox but while editing the value throws error.
2. If i use "selectedOption" it is not updating the values in the textbox itself.
I have even tried using the computed values to return the value, it works but if i try to change values in other options in the filter component the already updated values displays null or nothing.
Please help me. Is this problem can be solved using State Management Concept or do i have to have a separate compoenent other than App.Vue to do all this so that it would act as a parent/child kinda thing or is there anyother way to overcome this.
Try using watcher. If you watch for nselectedOption, everytime it changes, the watcher will fire and bind the changed value to selectedOption.
props: ['nselectedOption'],
data: {
selectedOption
},
watch: {
nselectedOption: function (val) {
this.selectedOption = val
}
}
Also, if the prop you are watching is an object/array, consider using spread operator if you want to make a local copy to avoid mutation.
this.someObj = { ...someProp }
Can't assign the value from mapState to data property after reloading the page, it works if you go to the child page but not if you are already standing in the child page and reloading the browser.
Computed mapState
computed: {
...mapState({
tsStore: state => state.SchemeStore
})
}
Data Property
data () {
return {
works: '',
offTime: '',
}
}
Mounted
if (this.tsStore.singleView) {
// Set data based on api.
let single = this.tsStore.singleView
this.works = single.works
this.offTime = single.offTime
}
After reloading works and offTime get empty in the data property.
Yes, the problem is the state being updated after the component was mounted;
So, the updated method is called instead of mounted.
It is visible in this fiddle, where the API call is simulated by the setTimeout:
https://jsfiddle.net/eywraw8t/369915/
I think the best way to get the component updated is using computed properties, where Vue implements proxies to watch for changes, like this fiddle:
https://jsfiddle.net/3mn2xgvr/
I moved the changes to a computed properties so when the state in Vuex changes, all data that depends on that changes.
This is more a "which method should I use" question, rather than a how to.
I have the following in my Vuex.Store() instance:
store.js:
export default new Vuex.Store({
state: {
acceptedTermsAndConditions: false
},
})
From various components I'm emitting an event which sets this.$store.state.acceptedTermsAndConditions to true or false, dependent on different User inputs.
However, in my component I would set the checked value of a "Accepts T&Cs" checkbox to this value, something like this:
components/Component.Vue:
data () {
return {
form: {
checkboxTermsAndConditions: this.$store.state.acceptedTermsAndConditions
}
}
}
I'm just not sure what method handles this? Does a solution require a getter? If not, what is the best way to watch for state changes and set data values accordingly?
If you want to set the checkbox state based on the stored value, you should use the computed object and the mapGetters helper function in your component:
https://vuex.vuejs.org/guide/getters.html#the-mapgetters-helper
computed: {
...mapGetters(['acceptedTermsAndConditions'])
}
Like this, the value will be accessible in your component. If you want to do the contrary (refresh the store based on the checkbox value), you should create a mutation in your store and you should use this in your component:
methods: {
...mapMutations(['setTACcheckbox'])
}
This way, inside your component you can refresh the store value with this.setTACcheckbox(value).
I've been using ...mapGetters a lot in my solution with success, but now that i need to access the variable directly in the data() section, it seems that the variable isn't set/ready when accessed..
the mapGetters are in the computed:{} section..
When debugging i notice that data() runs before computed:, so.. do i need to put a watch in some way here ?
Code :
data(){
return {
FiltersVisible: false,
orderList: {
currentPage: 1,
totalPages: ordersCount / 20,
// totalPages:80,
itemsPerPage: 20
}
}
},
computed: {
...mapGetters(['orders', 'ordersCount'])
// ...mapGetters(['orders'])
},
Screenshot of Vue state (Chrome)
Notice that the getters are initialized correctly....
There are many ways to tackle this. You can create a Vuex getter which supplies you a null value or default value to start with. This will at least ensure no errors and it will update whenever your store kicks into gear.
You could create a local computed property and fetch your store value with a mapGetter this way you can also supply a default.
You could have totalPages be set to 0 and use a watcher to update the value whenever your store value changes.
It really depends on context. For example a Vuex getter will be helpful if you need the same default fallback for other components who retrieve the value.
I am using an opensource vuejs + vuex project and this is the source https://github.com/misterGF/CoPilot/tree/master/src/components
I am currently having problems knowing how to trigger an event from one components to another.
I can use this.$state.store.commit("foo", "bar") to store information in vuex, but when two seperate have two difference export default {} I don't know how I can make the app aware whenever "foo" is for exampled changed to "baz" ... unless I refresh/reload the app, there is no way for me to know the changes
Use this.$store.watch on your component. Created() is a good place to put it. You pass it the state to watch and then specify the callback for when it changes. The Vuex docs do not give good examples. Find more information on this Vuejs Forum page. Store watch functions the same as the vm.$watch, so you can read more about that here in the Vue docs.
this.$store.watch(
(state)=>{
return this.$store.state.VALUE_TO_WATCH // could also put a Getter here
},
(newValue, oldValue)=>{
//something changed do something
console.log(oldValue)
console.log(newValue)
},
//Optional Deep if you need it
{
deep:true
}
)
Your question is not entirely clear so I am going to make some assumptions here.
If you simply want your app to know when a store value has changed you can use a watcher to watch a computed property that is directly linked to a store getter:
So you would set a watcher on something like this:
computed: {
doneTodosCount () {
return this.$store.getters.doneTodosCount
}
},
watch:{
doneTodosCount(value) {
console.log(`My store value for 'doneTodosCount' changed to ${value}`);
}
}
If you want your commit to behave differently depending on what the current value of your foo property is set to, then you can simply check for this in your commit function.
Let me know if you have some more questions.