V
V
Viktimius2021-03-16 10:08:23
Vue.js
Viktimius, 2021-03-16 10:08:23

How to organize the work of a store and a socket within one application?

Good day,

briefly about the project: messenger on nuxt (ui - vuetify), vue-socket.io. As it is already clear, I do not write messengers every day.

Problem

В мессенджере настроена обработка эвентов от сокета, прием и отправка сообщений, но не получается записать в объект стора сообщения - не отрабатывает мутация, хотя если обращаться к стору через this.$store.state.messages - запись происходит, но она не отслеживается nuxt. Вопрос как организовать стандартную обработку и хранение сообщений в сторе (actions, mutations, getters) ?! Звучит банально - но решения не нашел. Буду рад если подскажите куда копать или поделитесь примерами, ссылками на статьи.....


Question about google and bans
Не забанен ! Но решение не нашел.


Socket connection code

import Vue from 'vue';
import VueSocketIO from 'vue-socket.io';

export default function({store}) {
  Vue.use(new VueSocketIO({
    debug: true,
    connection: '********',
    vuex: {
        store,
        actionPrefix: 'SOCKET_',
        mutationPrefix: 'SOCKET_'
    },
  }))
}



Messaging component code

<template>
  <v-container fluid style='padding: 0;'>
    <v-row no-gutters>
      <v-col sm='12' style='position: relative;'>
        <div>
          <ChatWindow />
        </div>
        <div class='typer'>
          <input type='text' placeholder='Введите сообщение...' v-on:keyup.enter='sendMessage' v-model='message' />
          <v-btn icon class='blue--text emoji-panel'>
            <v-icon>mdi-emoticon-outline</v-icon>
          </v-btn>
        </div>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
import ChatWindow from '@/components/Chat/ChatWindow.vue';

export default {
  components: {
    ChatWindow,
  },
  data () {
    return {
      message: '',
      emojiPanel: false,
      currentRef: {},
      loading: false,
      totalChatHeight: 0,
      id: this.$route.params.id,
    }
  },
  methods: {
    sendMessage() { 
      this.$socket.emit( // эвент сокета, отправка сообщения
        'send_msg',
        {
          dialog_id: this.id,
          msg: this.message,
        }
      )

      this.$store.commit('updateMessageBySocket', {
        dialog_id: this.id,
        action: 'send_msg',
        message: this.message,
      });

      this.message = '';
    },
  },
}
</script>



Window component code (displaying a dialog between users)

<template>
  <v-container class='chat-window'>
    <v-container class='chat-container' @scroll='onScroll' >
      <div class='d-flex message' v-for="(message,index) in messages" :key="index">
        <v-container v-if='message.action === "send_msg"' class="message__wrap d-flex justify-end">
          <div class='d-flex flex-column justify-end col-5 message__box teal'>
            <div class="d-flex justify-space-between message__data-box">
              <div class='message__user'>Admin</div>
              <div class="message__date">{{ convertDate(message.created_at) }}</div>
            </div>
            <div class="d-flex justify-end message__content-box">
              <div class='content'>
                {{ message.message }}
              </div>
            </div>
          </div>
        </v-container>
        <v-container v-else-if='message.action === "receive_msg"' class="message__wrap d-flex justify-start">
          <div class='d-flex flex-column justify-start col-5 message__box blue'>
            <div class="d-flex justify-space-between message__data-box">
              <div class='message__user'>{{ `${dialog.user.first_name} ${dialog.user.last_name} ${dialog.user.username}` }}</div>
              <div class="message__date">{{ convertDate(message.created_at) }}</div>
            </div>
            <div class="d-flex justify-start message__content-box">
              <div class='content'>
                {{ message.message }}
              </div>
            </div>
          </div>
        </v-container>
      </div>
    </v-container>
  </v-container>
</template>

<script>
import { mapState, mapActions, mapGetters, mapMutations } from 'vuex';

export default {
  data () {
    return {
      id: this.$route.params.id,
    };
  },
  mounted() {
    this.fetchDialogByID(this.id); // информация по диалогу, кто с кем общается, когда начат диалог и т.д.(объект)
    this.fetchMessagesForDialogByID(this.id); // список сообщений(массив)
  },
  computed: {
    dialog() {
      return this.getCurrentDialog();
    },
    messages() {
      return this.$store.state.messages[this.id];
    }
  },
  methods: {
     .......
  },
}
</script>



Store

export const actions = {
....
SOCKET_receive_msg({ commit }, data) { // эвент сокета - получение сообщения
    const message = {
      dialog_id: data.dialog_id,
      action: 'receive_msg',
      message: data.msg,
      created_at: data.timestamp,
      not_read: !!data.unread,
    };

    console.log(message);
    commit('updateMessageBySocket', message);
  }

export const mutations = {
    updateMessageBySocket(state, payload) {
           // мутация изменения стора не срабатывает
           // пробовал разные варианты 
           // state.messages[payload.dialog_id].push(payload);   - вариант 1 
          //  const index = state.messages[state.dialog.id].length;   - вариант 2
          //  this._vm.$set(state.messages[state.dialog.id], index, payload); - вариант 2
  },
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
I
Ivan, 2021-03-16
@Viktimius

Perhaps the problem is VUE reactivity ?
In your very detailed description, the mutation key code is not given.
If you have a simple assignment there, like
state.message = payload
then try replacing it with the following line
Vue.set(state, 'message', payload)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question