Reactjs 在useEffect中使用useState值,而不进行状态更新useEffect

Reactjs 在useEffect中使用useState值,而不进行状态更新useEffect,reactjs,react-hooks,use-effect,use-state,Reactjs,React Hooks,Use Effect,Use State,我正在开发一个基于对象键管理字符串数组的函数。假设它看起来像这样: import React,{useState,useffect}来自“React”; 从“./上下文/字段上下文”导入字段上下文; 从“socket.io客户端”导入io; const[socket,setSocket]=useState(null); //由于WebSocket的原因,`data`数组每秒都会发生更改,以防这很重要 const[data,setData]=useState({foo:[],bar:[]}); c

我正在开发一个基于对象键管理字符串数组的函数。假设它看起来像这样:

import React,{useState,useffect}来自“React”;
从“./上下文/字段上下文”导入字段上下文;
从“socket.io客户端”导入io;
const[socket,setSocket]=useState(null);
//由于WebSocket的原因,`data`数组每秒都会发生更改,以防这很重要
const[data,setData]=useState({foo:[],bar:[]});
const[connections,setConnections]=useState([“conn1”,“conn2]”);
const{checkedFields}=useContext(FieldContext);//[“foo”,“moo”];
useffect(()=>{
设置连接(prevConnections=>{
//以下代码执行以下操作:
//循环通过临时连接(它是checkedFields的副本)
//A.如果'tempConn'是'data'对象中的一个键,则将带有'update\'前缀的名称推送到'\\\'数组中
//B.如果没有,只需将其不带前缀地推送到`_conns`数组
//由于`checkedFields`数组是['foo',moo],因此第一个元素将获得前缀,
//另一个不会,只会被推。
让_tempConns=[…checkedFields];
设_conns=[];
_tempConns.forEach(tempConn=>{
if(data[tempConn]!==未定义)_conns.push(`update${tempConn}`);
else _conns.push(tempConn);
});
返回连接;
});
},[checkedFields]);
//腹板钩
useffect(()=>{
const_socket=io(WS_URI);
_socket.on(“信息”,数据=>{
//这里发生了一些神奇的事情,添加到“data”对象中,这对于这个问题并不重要
});
固定插座(_插座);
}, [])

使用此挂钩时,我收到以下警告:
React hook useffect缺少依赖项:“data”。包括它或删除依赖项数组
。我理解,但是如果我在依赖项数组中包含
数据
,我会得到大量不必要的更新。我如何防止这种情况发生?(不使用
//eslint禁用下一行
请)

您不仅缺少
useffect
钩子的依赖项数组中的
数据
,而且还缺少依赖项数组中的
setConnections()
函数

您可以使用
useReducer
hook将状态更新逻辑移出
useffect
hook

const initialState = {
   data: { foo: [], bar: [] },
   connections: ["conn1", "conn2"]
} 

const reducerFunc = (state, action) => {
   switch(action.type) {
       case 'UPDATE_CONNECTIONS':
          let _tempConns = [...action.checkedFields];
          let _conns = [];
          _tempConns.forEach(tempConn => {
              if (state.data[tempConn] !== undefined) _conns.push(`update_${tempConn}`);
              else _conns.push(tempConn);
          });
          return { ...state, connections: _conns };
        default: 
          return state;
   }
};

const [myState, dispatch] = useReducer(reducerFunc, initialState);

const { checkedFields } = useContext(FieldContext); // ["foo", "moo"];

useEffect(() => {
    dispatch({ type: 'UPDATE_CONNECTIONS', payload: checkedFields });
}, [checkedFields]);
由于React确保
dispatch
函数不会更改,因此可以从
useffect
hook的依赖项数组中省略它

有关如何使用
useReducer
hook的详细信息,请参阅以下链接:

如果您可以在您的websocket中删除以下内容,并且没有其他
useEffect
s依赖于
数据
参考,则可以尝试使用

useRef返回一个可变的ref对象,其.current属性初始化为传递的参数(initialValue)。返回的对象将在组件的整个生命周期内持续存在


更新后,您的套接字似乎永远不会关闭。 如果您的组件卸载/重新装载,您将在后台添加一个新套接字。 然后在每次更新时,它会触发所有以前的套接字

套接字钩子应该返回一个close套接字函数。(我想,我从不直接使用插座)


(这不是你回答的答案,但有帮助:)

我一点也不懂,所以我不知道如何管理它。我添加了reducer函数的实现,它应该让你知道如何在你的代码中实现
useReducer
hook当
data
改变时,你还有其他需要运行的效果吗?是的,我有一个,这只是演示代码你好。通过您的更新(websocket),我发现了一个类似的例子。它使用的是Reducer^^:。希望它会有用我打算建议使用套接字更新
数据的
const data=useRef({foo:[],bar:[]})
。当前的
属性值直接。。。但是,如果您希望在
数据的引用更改时运行其他效果,那么它不可行,也不起作用……您是否缺少
数据
设置连接()
useffect
hook的依赖项数组中?@Yousaf useRef不要求在useffect中添加依赖项,我会更新我的答案以更精确。只有在卸载/重新装载时才会出现内存泄漏;)。这真的很奇怪,哈哈
// make `data` a ref object
// Pitfall: any changes to `data.current` will NOT be tracked 
const data = useRef({ foo: [], bar: [] })


// the websocket hook
useEffect(() => {
  ...
  _socket.on("info", data => {
    ...
    // update properties on `data.current`
    data.current.foo = 'some new value'
    data.current.bar = 'anoher new value;
  });
  
  ...
}, [])

useEffect(() => {
  setConnections(prevConnections => {
    ... 
    // reference data value from data.current
    const data = data.current

    ...
    return _conns;
  });
}, [checkedFields])

  useEffect(() => {
  const _socket = io(WS_URI);
  _socket.on("info", data => {
    // some magic happens here to add to the `data` object which is not important for this question
  });
  setSocket(_socket);
  return () => {_socket.close();}
}, [])