【问题标题】:Why is my state array resetting to empty?为什么我的状态数组重置为空?
【发布时间】:2020-11-15 13:20:09
【问题描述】:

由于某种原因,只有消息状态数组的最后一个元素正在呈现。每当我调用 addMessage 并打印消息的当前状态时,总是会打印出一个空数组。在我将新消息推送到状态数组后,该数组会打印出一条消息。为什么我的消息状态没有正确保存和重置为空数组?

const ChatApp = () => {
  const [messages, setMessages] = React.useState([]);

  useEffect(() => {
    ioClient.emit('join', { roomid: roomId });
    ioClient.emit('connected', { roomid: roomId });
  }, []);

  ioClient.on('message', (msg) => {
    const messageObject = {
      username: msg.from,
      message: msg.body,
      timestamp: msg.timestamp
    };
    addMessage(messageObject);
  });

  ioClient.on('send', (con) => {
    for (var key in con.arra) {
      var value = con.arra[key];
      const messageObject = {
        username: value.from,
        message: value.body,
        timestamp: value.timestamp
      };
      addMessage(messageObject);
    }
  });

  const sendHandler = (message) => {
     var res = moment().format('MM/DD/YYYY h:mm a').toString();
     ioClient.emit('server:message', {
       from: senderFullName,
       body: message,
       timestamp: res,
       roomId: roomId
     });
  };

  const addMessage = (message) => {
    console.log(messages);
    let messagess = [...messages, message];
    setMessages(messagess);
    console.log(messagess);
  };

  return (
    <div className="landing">
      <Container>
        <Row className="mt-5">
          <Col md={{ span: 8, offset: 2 }}>
            <Card style={{ height: '36rem' }} border="dark">
              <Messages msgs={messages} />
              <Card.Footer>
                <ChatInput onSend={sendHandler}></ChatInput>
              </Card.Footer>
            </Card>
          </Col>
        </Row>
      </Container>
    </div>
  );
};

ChatApp.defaultProps = {
  username: 'anonymous'
};

const mapStateToProps = (state) => {
  return {
    authUser: state.auth.user,
    profile: state.profile.profile
  };
};

export default connect(mapStateToProps)(ChatApp);

消息组件

import React from 'react';

import Message from './Message';

class Messages extends React.Component {
  componentDidUpdate() {
    // There is a new message in the state, scroll to bottom of list
    const objDiv = document.getElementById('messageList');
    objDiv.scrollTop = objDiv.scrollHeight;
  }

  render() {
    // Loop through all the messages in the state and create a Message component
    const messages = this.props.msgs.map((message, i) => {
        return (
          <Message
            key={i}
            username={message.username}
            timestamp={message.timestamp}
            message={message.message}
            fromMe={message.fromMe} />
        );
      });

    return (
      <div className='messages' id='messageList'>
        { messages }
      </div>
    );
  }
}

Messages.defaultProps = {
  msgs: []
};

export default Messages;

消息组件

import React from 'react';
import Container from 'react-bootstrap/Container';
import Image from 'react-bootstrap/Image';
import Card from 'react-bootstrap/Card';
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
import Button from 'react-bootstrap/Button';
import Media from 'react-bootstrap/Media';

class Message extends React.Component {
  render() {
    let now = this.props.timestamp;

    return (

      <ul className="list-unstyled">
              <Media.Body>
                <h6 className="font-weight-bold">{ this.props.username }</h6>
                <p>
                { this.props.message }
              </p>
                <p className="small text-muted">
                  {now}
              </p>
              </Media.Body>
            </Media>
      </ul>
    );
  }
}

Message.defaultProps = {
  message: '',
  username: '',
  to: '',
  fromMe: false
};

export default Message;

【问题讨论】:

  • 您确定您在&lt;Messages /&gt; 组件中正确处理了您的消息数组吗?
  • 除了状态更新应该是一个功能状态更新我看不到这个组件有任何明显的问题。你能用Messages组件代码更新问题吗?
  • @DrewReese 我更新了。
  • @DrewReese 和 useEffect 函数有关系吗?

标签: arrays reactjs socket.io react-redux react-state-management


【解决方案1】:

您正在为每个渲染创建事件处理程序。因此,即使在第一条消息之前,您也有 2 个不同的函数响应每个事件,因为函数组件在第一次实际渲染之前至少运行了两次。状态可能会在这些回调中丢失。

虽然这可能不是解决方案,但它肯定会消除不需要的行为:将绑定回调 ioClient.on 放入 useEffect

【讨论】:

  • 同样的问题依然出现
  • @asdfcoder 我们可能需要查看您的sendHandler 函数的代码来推断问题
  • @asdfcoder 唯一想到的是,如果您在每条消息后刷新浏览器页面。这样messages 永远不会有超过一项。否则一切看起来都很好,状态应该会正确更新
  • 据我所知,每条消息后浏览器页面都没有刷新。
【解决方案2】:

我将“addMessage(messageObject);`”行替换为:

setMessages((previousMessages) => [messageObject, ...previousMessages]);

通过将回调函数传递给 setMessages,我避免使用外部的状态对象。

【讨论】:

    猜你喜欢
    • 2020-08-25
    • 2020-01-22
    • 2013-10-14
    • 1970-01-01
    • 2019-10-18
    • 2020-07-28
    • 2020-10-09
    • 1970-01-01
    • 2017-12-28
    相关资源
    最近更新 更多