【问题标题】:React state always return initial valueReact 状态总是返回初始值
【发布时间】:2021-01-01 15:24:20
【问题描述】:

我正在使用 React、Next.js 创建接收 WebSocket 消息并记录这些消息的 Web 应用程序。

我的状态有问题。 当我引用状态时,总是返回初始值。

我的代码如下所示:

import React, { useState, useEffect } from 'react';
import { Container, Row, Col } from 'react-bootstrap';

export default function Home() {
  let socket = null;
  const [eventLog, setEventLog] = useState([]);
  const [updateFlag, setUpdateFlag] = useState(0);

  const onWebSocketMessage = (e) => {
    const data = JSON.parse(e.data);

    setEventLog(
      [
        {
          title: data.title,
          icon: data.icon,
          body: data.body,
          date: new Date(),
        },
      ].concat(eventLog)
    );

    setUpdateFlag(updateFlag + 1);
    console.log(updateFlag);
  };

  const connectWebSocket = (token) => {
    socket = new WebSocket('wss://localhost/' + token);
    socket.onmessage = onWebSocketMessage;
  };

  useEffect(() => {
    const token = localStorage.getItem('token');
    connectWebSocket(token);
  }, []);

  const eventLogHtml = eventLog.map((obj, index) => (
    <div key={index}>
      <h2>{obj.title}</h2>
      <div>
        <img src={obj.icon} style={{ width: '8rem' }} />
        <span>
          <p>{obj.body}</p>
          <p>{obj.date.toString()}</p>
        </span>
      </div>
    </div>
  ));
  return (
    <>
      <Container>
        <Row>
          <Col>
            <h1>Event log</h1>
            {eventLogHtml}
          </Col>
        </Row>
      </Container>
    </>
  );
}

在此代码中,eventLog 始终返回初始值 []。 而console.log(updateFlag); 总是记录 0。

我预计收到消息时eventLogconsole.log(updateFlag);会增加,但实际上只设置了最新的一个并且记录为0。

任何建议将不胜感激。 谢谢!

【问题讨论】:

    标签: reactjs next.js


    【解决方案1】:

    你有几个问题,例如:

    • 关闭updateFlag 值,该值不会在下一条消息中重新呈现
    • 重新分配值,例如 socket 和连接函数
    • setState 异步时记录一个陈旧的状态值。

    总结检查固定代码:

    let socket = null;
    
    export default function Home() {
      const [eventLog, setEventLog] = useState([]);
      const [updateFlag, setUpdateFlag] = useState(0);
    
      useEffect(() => {
        console.log(updateFlag);
      }, [updateFlag]);
    
      useEffect(() => {
        const onWebSocketMessage = (e) => {
          const data = JSON.parse(e.data);
    
          setEventLog((prev) => [
            {
              title: data.title,
              icon: data.icon,
              body: data.body,
              date: new Date(),
            },
            ...prev,
          ]);
    
          setUpdateFlag((prev) => prev + 1);
        };
    
        const token = localStorage.getItem("token");
        socket = new WebSocket("wss://localhost/" + token);
        socket.onmessage = onWebSocketMessage;
      }, []);
    
      ...
    }
    

    【讨论】:

    • 我必须在 onWebSocketMessage 函数中引用 updateFlag 值...有没有办法在 onWebSocketMessage 函数中引用更新值?
    【解决方案2】:

    因为你要在useEffect 上添加dependencies。试试这个

    useEffect(() => {
        const token = localStorage.getItem('token');
        connectWebSocket(token);
    }, [eventLog]);
    

    正如丹尼斯所说。当eventLog 更改时,它会重新连接 websocket。所以你必须拆分连接和监听事件。

    const token = localStorage.getItem("token");
    socket = new WebSocket("wss://localhost/" + token);
    //outside function component
    
    useEffect(() => {
      const onMessage = () => {// do stuff}
      socket.on('message', onMessage)
    
      return () => socket.off('message', onMessage)
    }, [eventLog, updateFlag])
    

    【讨论】:

    • 与问题有什么关系?您只是在每个日志上重新建立与套接字的连接,为什么要这样做?
    • 我认为它必须将 intit connect websocket 移动到其他零依赖的 useEffect 。以及其他 userEffect 的侦听器 onmessage。对不起我的懒惰。我现在要编辑我的答案。
    猜你喜欢
    • 2019-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-28
    • 2021-09-30
    • 1970-01-01
    • 2020-11-01
    相关资源
    最近更新 更多