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的详细信息,请参阅以下链接:
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();}
}, [])