Socket.io - React: Как получить сохраненные данные socket.io (MongoDB) в React? - PullRequest
0 голосов
/ 27 февраля 2019

Я следовал нескольким учебникам о том, как отображать сообщения, отправленные в чате перед присоединением, но я не знаю, как отображать их в React, и у меня есть несколько вопросов ниже на стороне сервера.

Клиентсторона, в конструкторе:

this.state = {
 msg: "",
 messages: []
};

Клиентская сторона, у меня есть форма, нажатие кнопки которой отправит сообщение на сервер с помощью этой функции:

sendMessage(e) {
 e.preventDefault();
 let msg = this.state.msg;
 this.socket.emit("sendMessage", msg);
 this.setState({ msg: "" });
}

Серверная сторона, у меня естьmongoose Схема для сообщения с именем Message и коллекцией в базе данных является messages.

const Message = new mongoose.Schema({
 sender: {
  type: "string"
 },
 message: {
  type: "string"
 }
});

var messages = [];

io.on("connection", (socket, user) => {
var user = socket.request.session.user;

Message.find({}).exec((err, messages) => {
 if (err) throw err;
 console.log(messages);
 io.emit("showingPastMessages", messages);
});

console.log (messages) показывает в PowerShell все сообщения (записи), сохраненные в Mongo в массиве объектов javascript?[{id_: 4qxxx, отправитель: 'user123', сообщение: 'hello!'}, {id_: 5exxx, отправитель: 'user456', сообщение: 'hi!'}] Я хотел бы знать, возможно ли получить доступтолько отправителю и свойствам сообщения отправить его клиенту?Что-то вроде messages.sender + messages.message, потому что когда я console.log (messages.message) показывает неопределенное

Здесь сервер получает отправленное сообщение и сохраняет его в Mongo.

socket.on("sendMessage", function(msg) {
var newMsg = new Message({ message: msg, sender: user });
 newMsg.save(function(err) {
   if (err) {
     console.log(err);
   } else {
     messages.push(newMsg);
     console.log(newMsg);
     console.log(messages);
   }
 });
});

console.log (newMsg) показывает последнее отправленное сообщение, но console.log (messages) не показывает предыдущие сообщения, а только последнее, почему?

тогда в React мне следуетесть что-то подобное в конструкторе, в ComponentDidMount ()?Если это должно быть с prevState

this.socket.on("showingPastMessages", function(messages){
 this.setState({ ...this.state.messages, messages})
});

Не могли бы вы дать мне несколько советов?

Вот мой код на стороне клиента для получения данных:

class Chat extends Component {
 constructor(props) {
 super(props);

 this.state = {
  msg: "",
  messages: []
 };

 var socket = io('http://localhost:3000');
 this.socket.on("history", function(messages) {
  console.log(messages);
 });
}

1 Ответ

0 голосов
/ 27 февраля 2019

Это хорошее начало.То, что я предложил бы сделать, это сделать это немного более управляемым событием.Чтобы сделать это, вы хотите добавить сокеты в комнату, когда они соединяются.Сколько комнат и как их разделить, будет зависеть от вашего приложения, но я продемонстрирую основную идею.

Во-первых, когда сокет подключается к вашему серверу, добавьте этот сокет в комнату и испуститеистория чата немедленно.

io.on('connection', async (socket) => {
  socket.user = socket.request.session.user;

  socket.join('chat');

  try {
    const messages = await Message.find({});

    socket.emit('history', messages);
  } catch (err) {
    // Handle this error properly.
    console.error(err);
  }
});

Затем, позже, когда вы получите сообщение, вы захотите сохранить это сообщение и отправить его во все сокеты вашей комнаты чата.

socket.on("sendMessage", (msg, callback) => {
  const message = new Message({ message: msg, sender: socket.user });

  message.save(function(err) {
    if (err) {
      return callback(err);
    }

    io.to('chat').emit('message', message);
  });
});

Наконец, на стороне клиента вы захотите прослушать событие истории.Получив его, вы захотите очистить текущую историю чата и заменить ее тем, что сообщает сервер.Возможно, это будет выглядеть примерно так:

socket.on('history', (messages) => {
  this.setState({ messages });
});

Вы также захотите прослушать это событие message, но с этим событием вы только добавите сообщение в свою историю.Это может выглядеть примерно так:

socket.on('message', (message) => {
  this.setState({ messages: [ ...messages, message ] });
});

Слово предупреждения, если, когда вы сообщаете серверу о новом сообщении, не добавляйте его в массив состояний messages, пока не получите событие message.Если вы сделаете это, вы заметите двойные сообщения.Например, это может выглядеть примерно так:

onSendMessage(evnt) {
  evnt.preventDefault();

   socket.emit("sendMessage", msg);
   this.setState({ msg: "" });
}

Примечание : Получив некоторую обратную связь от OP, я хотел добавить раздел о том, куда поместить обработчики событий, прикрепленные к сокету.(т.е. все socket.on с).Я предлагаю добавить этот код в файл, который определяет схему Message внизу файла в обратном вызове io.on('connection').Например,

const Message = new mongoose.Schema({/*...*/});

io.on('connection', (socket) => {
  // Everything else I wrote above...

  socket.on('sendMessage', (msg, callback) => {
    // ...
  });
});

На стороне клиента обработчики событий, вероятно, будут зарегистрированы при подключении компонента чата.Например,

class ChatComponent extends React.Component {
  componentDidMount() {
    this.socket = io('https://your-server-or-localhost/');

    this.socket.on('history', (messages) => {
      // See above...
    });
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...