Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 更新React useEffect中的非状态变量_Reactjs_React Hooks - Fatal编程技术网

Reactjs 更新React useEffect中的非状态变量

Reactjs 更新React useEffect中的非状态变量,reactjs,react-hooks,Reactjs,React Hooks,我有一个应用程序,它每秒通过WebSocket接收新数据。每秒钟我都会收到10到15条需要存储和显示的信息。当前,每次收到新数据时,我都会更新状态数组,但效果是每秒重新渲染屏幕10到15次 我想要实现的是将传入数据存储在一个数组中,但每秒只更新一次屏幕。 我无法使用的方法是创建一个非状态数组,在接收到新数据时更新该数组,并使用计时器每秒将该数据复制到状态数组 这是状态数组的声明: const [boatData2, _setBoatData2] = useState({}); c

我有一个应用程序,它每秒通过WebSocket接收新数据。每秒钟我都会收到10到15条需要存储和显示的信息。当前,每次收到新数据时,我都会更新状态数组,但效果是每秒重新渲染屏幕10到15次

我想要实现的是将传入数据存储在一个数组中,但每秒只更新一次屏幕。

我无法使用的方法是创建一个非状态数组,在接收到新数据时更新该数组,并使用计时器每秒将该数据复制到状态数组

这是状态数组的声明:

  const [boatData2, _setBoatData2] = useState({});
  

  const boatDataRef = useRef(boatData2);
  
  const setBoatData2 = (update) => {
    boatDataRef.current = update;
    _setBoatData2(update);
  }
这是接收数据的钩子代码:

  useEffect(() => {
    if (!ws.current) return;
    ws.current.onmessage = e => {
      setDataFlowing(true);
      setDataAge(0);
      setScreenUpdates(screenUpdates => screenUpdates + 1);
      //console.log('New Data');
      const message = JSON.parse(e.data);
      if (message.updates && message.updates.values) {
        message.updates[0].values.forEach(obj => {
          let newPath = obj.path.split('.').join("");
          const update = {
            path: obj.path,
            value: obj.value,
            timestamp: message.updates[0].timestamp,
            valid: true,
            age: 0,
          };
          now = Date.parse(message.updates[0].timestamp);
          setBoatData2({ ...boatDataRef.current, [newPath]: update });
        });
      }
    };
  }, []);
这是每秒运行的代码:

  useEffect(() => {
    let interval = null;
    if (isActive) {
      interval = setInterval(() => {
        setSeconds(seconds => seconds + 1);
        let boatdata = boatData2;
        //console.log(boatData3);
        Object.values(boatdata).forEach(val => {
          val.age = val.age + 1;
          if (val.age > 30) {
            val.valid = false;
          }
        });
        setBoatData2(boatdata);
        setDataAge(dataAge => dataAge + 1);

        if (dataAge > 60) {
          setDataFlowing(false);
        }
      }, 1000);
    } else if (!isActive && seconds !== 0) {
      clearInterval(interval);
    }
    return () => clearInterval(interval);
  }, [isActive, seconds, boatData2]);

您可以在
useRef
的帮助下执行此操作

const messageRef = useRef([]); 
这会在
messageRef
中创建一个名为
current
的对象,我们可以对其进行变异,而对其进行变异不会触发重新渲染。现在,您的
messageRef
将如下所示

{ 
  current: []
}
现在,无论何时从websocket获得消息,都将消息按如下所示推入此引用中

messageRef.current.push(your message)
现在,在函数中,它会在某个xyz秒后更新状态。可以使用此引用更新状态

setYourMessages(messageRef.current);
messageRef.current = []; // do this after you state update call. Else you will be pushing duplicate messages into the state