Vuex: se asignó el "nombre" de la propiedad calculada, pero no tiene un establecedor

108

Tengo un componente con alguna validación de formulario. Es un formulario de pago de varios pasos. El siguiente código es para el primer paso. Me gustaría validar que el usuario ingresó un texto, almacenar su nombre en el estado global y luego enviarlo al siguiente paso. Estoy usando vee-validate y vuex

<template>
<div>
    <div class='field'>
        <label class='label' for='name'>Name</label>
        <div class="control has-icons-right">

            <input name="name" v-model="name" v-validate="'required|alpha'" :class="{'input': true, 'is-danger': errors.has('name') }" type="text" placeholder="First and Last">
            <span class="icon is-small is-right" v-if="errors.has('name')">
                <i class="fa fa-warning"></i>
            </span>
        </div>
        <p class="help is-danger" v-show="errors.has('name')">{{ errors.first('name') }}</p>

    </div>
    <div class="field pull-right">
        <button class="button is-medium is-primary" type="submit" @click.prevent="nextStep">Next Step</button>
    </div>
</div>
</template>

<script>
export default {
    methods: {
        nextStep(){
            var self = this;

            // from baianat/vee-validate
            this.$validator.validateAll().then((result) => {
                if (result) {
                    this.$store.dispatch('addContactInfoForOrder', self);
                    this.$store.dispatch('goToNextStep');
                    return;
                }
            });
        }
    },
    computed: {
        name: function(){
            return this.$store.state.name;
        }
    }
}
</script>

Tengo una tienda para manejar el estado del pedido y registrar el nombre. En última instancia, me gustaría enviar toda la información del formulario de varios pasos al servidor.

export default {
  state: {
    name: '',
  },

  mutations: {
    UPDATE_ORDER_CONTACT(state, payload){
      state.name = payload.name;

    }
  },

  actions: {
    addContactInfoForOrder({commit}, payload) {
      commit('UPDATE_ORDER_CONTACT', payload);
    }
  }
}

Cuando ejecuto este código, aparece un error que Computed property "name" was assigned to but it has no setter.

¿Cómo vinculo el valor del campo de nombre al estado global? Me gustaría que esto sea persistente para que incluso si un usuario retrocede un paso (después de hacer clic en "Paso siguiente"), verá el nombre que ingresó en este paso.

Connor sanguijuela
fuente
1
Además de la respuesta de Roy J, parece que usar v-foren un calculado sin un colocador arroja esta advertencia también.
jsiegal

Respuestas:

192

Si va a v-modeluna computadora, necesita un setter . Lo que sea que quiera que haga con el valor actualizado (probablemente escríbalo en el $store, considerando que de eso lo extrae su getter) lo hace en el setter.

Si la devolución a la tienda se realiza mediante el envío de un formulario, no desea hacerlo v-model, solo desea configurarlo :value.

Si desea tener un estado intermedio, donde se guarda en algún lugar pero no sobrescribe la fuente en el $storeenvío del formulario hasta, deberá crear un elemento de datos de este tipo.

Roy J
fuente
38
:valueterminado v-model. ¡Gracias!
Connor Leech
4
Gracias ... arreglé mi [vue warn] también. Tenía un cajón de navegación que requería (solo lectura) valor verdadero / falso, pero le había puesto un modelo v.
GA
26

Debería ser así.

En su componente

computed: {
        ...mapGetters({
                nameFromStore: 'name'
            }),
        name: {
           get(){
             return this.nameFromStore
           },
           set(newName){
             return newName
           } 
        }
    }

En tu tienda

export const store = new Vuex.Store({
         state:{
             name : "Stackoverflow"
         },
         getters: {
                 name: (state) => {
                     return state.name;
                 }
         }
}
OhhhQueVarun
fuente
1
Perdón por revivir una vieja respuesta tuya, pero ¿por qué usar un captador en este caso? ¿Por qué no devolver this.nameFromStore de mapState? Funciona igual de bien aparentemente.
Jake
@Jake Para este ejemplo dado, lo que está diciendo es correcto. Pero cuando desee manipular los datos guardados en la tienda, puede hacerlo dentro del getter, pero si los usa this.nameFromStoredirectamente, no podrá manipular los datos.
OhhhThatVarun
1
Gracias por la aclaración :)
Jake
@Jake ¡No hay problema!
OhhhThatVarun
3

Para mí estaba cambiando.

this.name = response.data;

A lo que calcula regresa así;

this.$store.state.name = response.data;
Ibn Rushd
fuente
0

Solo quiero mencionar por qué aparece esta advertencia, siempre que creamos un valor calculado, es un captador de forma predeterminada, necesitamos definir explícitamente los definidores para la propiedad calculada,

como se menciona en la documentación de VueJs, Computed Setter

su propiedad calculada se verá así

   name: {
       get: function () {
          return yourName
       },
       set: function (newName) {
          return yourNewName
       }

La forma más adecuada es utilizar mapStatepara obtener el nombre de la tienda, y otra opción que define el getter en su tienda y usa mapGetterspara extraer el nombre de la tienda,

Lo importante que debe saber: los captadores en la tienda se utilizan cuando desea obtener datos calculados de la tienda, luego, en ese momento, define la lógica en captadores que obtienen datos calculados

ejemplo de getter

getters = {
  isLoggedIn (state) {
    return !!state?.activeUser?.id
  }
}

este getter verifica su estado para el usuario activo y devuelve verdadero si está conectado y falso si no está conectado,

más adelante, en toda la aplicación, usamos mapGetterspara extraer esta isLoggedInpropiedad y agregar controles de acuerdo con eso

espero que alguien encuentre esta ayuda completa :)

Hanzla Habib
fuente