反应+ useState +数组+突变=错误

时间:2019-08-17 17:46:39

标签: javascript arrays reactjs socket.io

在函数writeMessage上,我需要使用传入的新消息填充名为chat的数组。为此,我尝试了三种没有运气的选择。没有突变,它们仅采用initalState并丢弃其他更改。随着突变,它不会重新呈现自己。任何帮助将不胜感激。

const writeMessage =(msg)=> {        // newChat = chat.concat(msg);        // newChat = [... chat,msg];这两个具有初始状态,但不适用于修改状态        // setChat(newChat);        chat.push(msg); //此方法会更改:(并起作用,但不会重新渲染自身       }

我的代码:

import React, {useEffect, useState} from 'react';
import openSocket from 'socket.io-client';
import './App.css';

const App = () => {
  var socket = openSocket('http://localhost:3001/')
  var newChat= [];

  const [message, setMessage] = useState("");
  const [chat, setChat] = useState([{msg:"Hola"},{msg:"Todo Bien?"}])

  useEffect(() => {  
    socket.on('new message', function(msg){
      writeMessage(msg)
     });
  },[])

  const writeMessage = (msg) => {
   //newChat = chat.concat(msg); 
   //newChat = [...chat, msg]; this two takes inital State, but doesn not work with modified state 
   //setChat(newChat);
   chat.push(msg); //this mutates :( and works, but does not re-render itself
  }

  const sendMessage = () => {
    if(message === ""){
      alert("Write something please");
    }else{
      socket.emit('send message', message);
      setMessage("");
    }
    console.log(chat);
}

  return (
    <div>
    <ul id="messages">{chat.map((msg, index) => <li key={index}>{msg.msg}</li>)}</ul>
      <form>
        <input id="m" autoComplete="off" value={message} onChange={(e) => setMessage(e.target.value)}/>
        <button type="button" onClick={sendMessage}>Send</button>
      </form>
      
    </div>)
}

export default App
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

我希望在不进行任何更改的情况下将新消息添加到阵列中,并保持以前发送的消息。

2 个答案:

答案 0 :(得分:1)

使用useState时,可以使用prevState和散布运算符来创建一个像这样的新数组。

const writeMessage = (msg) => {
  setChat((prevState) => [...prevState, msg]);
}

使用此方法,您无需更改状态,组件即可再次呈现。

答案 1 :(得分:0)

我认为您正在尝试直接更改聊天内容。请改用setChat

编辑: 您应该将userReducer设置为非原始值。 https://reactjs.org/docs/hooks-reference.html#usereducer

  const writeMessage = (msg) => {
   setChat([...chat, newChat]); // This should re-render
  }