Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

assigning to a computed property without setter does not fail #6078

Closed
mitar opened this issue Jul 12, 2017 · 8 comments
Closed

assigning to a computed property without setter does not fail #6078

mitar opened this issue Jul 12, 2017 · 8 comments

Comments

@mitar
Copy link
Contributor

mitar commented Jul 12, 2017

What problem does this feature solve?

If I have a computed property with only getter, setter is set to a noop. If I then try to assign to such a computed property, nothing happens. This can hide programming errors.

What does the proposed API look like?

I would suggest that when not in production, instead of a noop a warning function would be assigned to a setter and a warning message would be printed if one tries to assign a value to such computer property.

Alternatively, output of computed property without setter could be configured without a setter at all, as a read-only property.

@Plortinus
Copy link

Plortinus commented Aug 4, 2017

@yyx990803
Now with the vue version v2.4.2, when I put a state into the computed property by the mapState helper function,I get a warn [Vue warn]: Computed property "isLoading" was assigned to but it has no setter.

I couldn't find setter in the vuex state,so I think the warn may should consider this condition.

codes like this:

// store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const state = {
  isLoading: false
}

const mutations = {
  updateLoadingStatus (state, payload) {
    state.isLoading = payload.isLoading
  }
}

export default new Vuex.Store({
  state,
  mutations
})
// App.vue
<template>
  <div id="app">
    <router-view></router-view>
    <loading v-model="isLoading"></loading>
  </div>
</template>

<script>
  import { Loading } from 'vux'
  import { mapState } from 'vuex'

  export default {
    name: 'app',
    components: {
      Loading
    },
    computed: {
      ...mapState({
        isLoading: state => state.isLoading
      })
      }
    }
  }
</script>

@posva
Copy link
Member

posva commented Aug 4, 2017

@Plortinus That happens because of the v-model. It' trying to change the value of isLoading but mapState will only create getters. You can probably make things work by binding the value to the isLoading and then handle the update by committing the mutations on the @input

@Plortinus
Copy link

@posva

Thanks a lot.I tried to use the sync modifier to handle this problem.It works.

But I am wondering if my solution is a good practice or not.The purpose of these codes is to show a loading toast when switch one page to another page in an SPA.

<template>
  <div id="app">
    <router-view></router-view>
    <loading :value.sync="isLoading"></loading>
  </div>
</template>

<script>
  import { Loading } from 'vux'
  import { mapState } from 'vuex'

  export default {
    name: 'app',
    components: {
      Loading
    },
    computed: {
      ...mapState({
        isLoading: state => state.isLoading
      })
    }
  }
</script>

@LinusBorg
Copy link
Member

LinusBorg commented Aug 4, 2017

Why/when would the <loading> component ever want to change the value of "isLoading"? That component can hardly know when the process is over, can it?

So I don't see a need for .sync or v-model or anything like it.

@Plortinus
Copy link

I update the value of isLoading before/after the router action.

router.beforeEach(function (to, from, next) {
  store.commit('updateLoadingStatus', { isLoading: true })
  next()
})

router.afterEach(function (to) {
  store.commit('updateLoadingStatus', { isLoading: false })
})

@LinusBorg
Copy link
Member

LinusBorg commented Aug 4, 2017

Yeah sure, but then that value will go from your parent component down to the <loading> compoent, not up from the loading component. That value is not changed in the <loading> component, which is the only situation that you would need v-model or .sync for.

Maybe you have a missunderstanding how props work, at least in combination with computed properties?

@Arnoldmn
Copy link

Arnoldmn commented Mar 23, 2019

okay mate this is a snippet of my code maybe it may help you figure out where you are wrong but i Think it should be easier now since i also had the same error but with getter

`computed: {
comparePasswords() {
return this.password !== this.confirmPassword
? "Passwoeds do not match!"
: "";
},
user() {
return this.$store.getters.user;
}
},

watch: {
user: function(value) {
if (value !== null && value !== undefined) {
this.$router.push("/");
}
}
},`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants