【问题标题】:React + useState + Array + Mutation = errorReact + useState + Array + Mutation = error
【发布时间】:2019-08-17 17:46:39
【问题描述】:

在函数 writeMessage 上,我需要用传入的新消息填充名为 chat 的数组。为此,我尝试了三种没有运气的替代方案。如果没有突变,它们只会采用 initalState 并丢弃其他更改。并且随着突变,它不会重新渲染自己。任何帮助将不胜感激。

const writeMessage = (msg) => { //newChat = chat.concat(msg); //newChat = [...聊天,消息];这两个采用初始状态,但不适用于修改状态 //setChat(newChat); 聊天推送(味精); //this mutates :( 并且可以工作,但不会重新渲染自己 }

我的代码:

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>

我希望将新消息添加到数组中而不进行变异并保留之前发送的消息。

【问题讨论】:

    标签: javascript arrays reactjs socket.io


    【解决方案1】:

    使用 useState 时,可以使用prevState 和扩展运算符来创建这样的新数组。

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

    使用这种方法,您不会改变状态并且组件会再次呈现。

    【讨论】:

    • 这是我的问题的正确答案。谢谢。
    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 2021-02-07
      • 2022-09-23
      • 1970-01-01
      • 2021-09-18
      • 2019-01-26
      • 2021-10-12
      • 2021-11-17
      • 1970-01-01
      • 2020-06-27
      相关资源
      最近更新 更多