如何更新reactjs中的状态?

时间:2018-10-27 19:28:26

标签: javascript reactjs

我已经使用reactjs,nodejs,mongodb创建了聊天应用程序。我将数据存储在mongodb中,但是在通过消息数组进行映射时,为什么在聊天应用程序中不显示消息?

我正在使用message状态变量来存储单个消息,并且所有这些单个消息都被添加到messages数组(state variable)内。我设置了message: "" and date : "",但是即使在屏幕上显示消息之前,我的情况也被设置为空字符串。如何在消息上映射并在聊天应用程序中显示所有消息?

代码:

server.js:

const express = require('express');
const mongoose = require('mongoose');
const socket = require('socket.io');
const message = require('./model/message')

const app = express();

const mongoURI = require('./config/keys').mongoURI;

mongoose.connect(mongoURI, {useNewUrlParser: true}, function (err,res) {

    if(err){
      console.log("There is error: " + err);
    }else{
      console.log("Connected to mongo database") 
    }

})

let db = mongoose.connection;

db.once('open', function() {
  console.log("Database is now connected");

  let io =  socket(server);

io.on("connection", function(socket){
  console.log("Socket Connection Established with ID :"+ socket.id)

  socket.on('disconnect', function(){
    console.log('User Disconnected');
  });

  let chat = db.collection('chat');

      socket.on('SEND_MESSAGE', function(data){
        let message = data.message;
        let date = data.date;

        // Check for name and message
        if(message !== '' || date !== ''){
            // Insert message
            chat.insert({message: message, date:date}, function(){
                socket.emit('RECEIVE_MESSAGE', [data]);
            });
        }
    });

    chat.find().sort({_id:1}).toArray(function(err, res){
      if(err){
          throw err;
      }
      // Emit the messages
      socket.emit('RECEIVE_MESSAGE', res);
    });

}) 

});


const port = 5000;

let server = app.listen(5000, function(){
  console.log('server is running on port 5000')
});

messages.js:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// Create Schema
const MessageSchema = new Schema({
  message: {
    type: String,
    required: true
  },
  date: {
    type: Date,
    default: Date.now
  }
});

module.exports = mongoose.model('Message', MessageSchema);

chat.js:

import React, { Component } from 'react'
import './chat.css'
import io from "socket.io-client";

export default class Chat extends Component {

    constructor(props){
        super(props);

        this.state = {
            message: '',
            date: '',
            messages: []
        };
        this.sendMessage = this.sendMessage.bind(this);
        this.addMessage = this.addMessage.bind(this);

        this.socket = io('localhost:5000');
    }

    componentDidMount() {
      this.socket.on('RECEIVE_MESSAGE', data => {
          this.addMessage(data);
      });
    }

    sendMessage(event) {
      event.preventDefault();

      if(this.state.message !== ''){
        this.socket.emit('SEND_MESSAGE', {
            message: this.state.message,
            date: Date.now()
        });
      }
    };

    addMessage(data) {
      this.setState({
        messages: [...this.state.messages, data],
        message: '', 
        date: ''
      });
      console.log(this.state.messages);
    };

    render() {
        return (
        <div>
                <div id="status"></div>
                <div id="chat">
                    <div className="card">
                        <div id="messages" className="card-block">
                            {this.state.messages.map((message, index) => {
                                    return (
                                        <div key={index} className="msgBox"><p className="msgText">{message.message}</p></div>
                                    )
                            })}
                        </div>
                    </div>
                    <div className="row">
                        <div className="column">
                            <input id="inputmsg" type="text" placeholder="Enter Message...."
                            value={this.state.message} onChange={ev => this.setState({message: ev.target.value})}/>
                        </div>
                        <div className="column2">
                            <button id="send" className="button" onClick={this.sendMessage}>Send</button>
                        </div>
                    </div>
                </div>
        </div>
        )
    }
}

console.log(this.state.messages)的屏幕截图:

enter image description here

1 个答案:

答案 0 :(得分:1)

从服务器端代码来看,您似乎确实将RECEIVE_MESSAGE作为数组发出,因此执行[ ...state.messages, data ]会导致在react中创建多维数组。您可以通过RECEIVE_MESSAGE发出一条消息,也可以将addMessage更改为[ ...state.messages, ...data ]

要对此进行更多说明: 因此,起初,您的messages状态设置为空数组。然后,您所有的旧消息都从套接字作为数组(数据)来自套接字,并且调用addMessage并尝试扩展state.messages的元素(此时仍为空),然后添加一个{{1}新数组末尾的}(这是一个数组)被设置为state。结果是您得到一个包含一个元素的数组:所有先前的消息(数组中的数组)。当收到新消息时,data进行相同的扩展,因此addMessage被扩展到一个新的数组中,并且state.messages(又是一个数组)被添加到其末尾。结果是具有两个元素的数组:第一个在开始时添加的数组(数据)和新的。通过在data函数中执行...data,您可以散布实际的数据数组并将其元素置于状态而非数组本身的状态,因此addMessage就像两个数组中元素的串联一样:[ ...state.messages, ...data ]state.messages