Vuex - A propriedade computada “nome” foi atribuída, mas não tem setter

108

Eu tenho um componente com alguma validação de formulário. É um formulário de verificação de várias etapas. O código abaixo é para a primeira etapa. Eu gostaria de validar se o usuário inseriu algum texto, armazenar seu nome no estado global e então enviar para a próxima etapa. Estou usando vee-validate e 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>

Tenho uma loja para lidar com o estado do pedido e registrar o nome. Em última análise, gostaria de enviar todas as informações do formulário de várias etapas para o servidor.

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

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

    }
  },

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

Quando eu executo este código, recebo um erro que Computed property "name" was assigned to but it has no setter.

Como vinculo o valor do campo de nome ao estado global? Eu gostaria que isso fosse persistente, de forma que mesmo se um usuário voltar uma etapa (depois de clicar em "Próxima etapa"), ele verá o nome que inseriu nesta etapa

Connor Leech
fonte
1
Além de resposta de Roy J, parece como se estivesse usando v-forem um calculado sem um setter lança este aviso também.
jsiegal

Respostas:

192

Se você está indo para v-modelum computador, ele precisa de um configurador . O que quer que você queira fazer com o valor atualizado (provavelmente escreva para o $store, considerando que é disso que seu getter o extrai), você faz no setter.

Se a gravação de volta para a loja acontecer por meio do envio do formulário, você não deseja v-model, apenas deseja definir :value.

Se você deseja ter um estado intermediário, onde é salvo em algum lugar, mas não sobrescreve a fonte no $storeenvio do formulário até, você precisará criar tal item de dados.

Roy J
fonte
38
:valueacabou v-model. Obrigado!
Connor Leech
4
Obrigado ... consertou minha [advertência] também. Eu tinha uma gaveta de navegação que exigia valor verdadeiro / falso (somente leitura), mas coloquei um modelo em v nela.
GA
26

Deve ser assim.

Em seu componente

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

Em sua loja

export const store = new Vuex.Store({
         state:{
             name : "Stackoverflow"
         },
         getters: {
                 name: (state) => {
                     return state.name;
                 }
         }
}
OhhhThatVarun
fonte
1
Desculpe por reviver uma velha resposta sua, mas por que usar um getter neste caso? Por que não retornar this.nameFromStore de mapState? Parece que funciona tão bem.
Jake
@Jake Para este exemplo dado, o que você está dizendo está certo. Mas quando você deseja manipular os dados salvos no armazenamento, você pode fazer isso dentro do getter, mas se usar this.nameFromStorediretamente, não poderá manipular os dados.
OhhhThat Varun
1
Obrigado pelo esclarecimento :)
Jake
@Jake Não tem problema!
OhhhThat Varun
3

Para mim estava mudando.

this.name = response.data;

Para o que computado retorna assim;

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

Só quero mencionar por que esse aviso aparece, sempre que criamos um valor computado, ele é getter por padrão, precisamos explicitamente definir setters para propriedade computada,

conforme mencionado na documentação de VueJs, Computed Setter

sua propriedade computada ficará assim

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

A maneira mais apropriada é usar mapStatepara obter o nome da loja, e outra opção que você define getter em sua loja e usa mapGetterspara extrair o nome da loja,

Uma coisa importante a saber: getters in store são usados ​​quando você deseja obter dados computados da loja, então, nesse momento, você define a lógica em getters que obtêm dados computados

exemplo de getter

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

este getter verifica seu estado para o usuário ativo e retorna verdadeiro se estiver conectado e falso se não estiver conectado,

mais tarde, em todo o aplicativo, usamos mapGetterspara extrair essa isLoggedInpropriedade e adicionar verificações de acordo com o

espero que alguém encontre esta ajuda completa :)

Hanzla Habib
fonte