有时会从WebSocket收到newItem
,并通过saveNewItem
保存到useState
然后按预期开始useEffect
块。
更新。如果closeArray
中有一个与openTime
相同的newItem
对象,我想用closeArray
替换newItem
中的对象,因为它将一个新的close
添加。如果closeArray
中没有打开时间与newItem
相同的对象,我想将新项目推送到数组中。
删除。最后,如果数组的长度超过39个对象,我想删除第一项。
如果我将closeArray
添加到useEffect
依赖项数组中,我将创建一个讨厌的循环,如果我不添加它,closeArray
将不会更新
我希望usEffect
仅在newItem
更改时才触发,而不是closeArray
更改时才触发,但我仍想获取{{1 }}
closeArray
如果我确实将useEffect
添加到interface CloseInterface {
openTime: number;
closeTime: number;
close: number;
}
function App() {
const [newItem, saveNewItem] = useState<CloseInterface>();
const [closeArray, saveCloseArray] = useState<CloseInterface[]>([]);
useEffect(() => {
if (newItem) {
let found = false;
let arr = [];
for (let i = 0; i < closeArray.length; i++) {
if (closeArray[i].openTime === newItem.openTime) {
found = true;
arr.push(newItem);
} else {
arr.push(closeArray[i]);
}
}
if (found === false) {
arr.push(newItem)
}
if (arr.length === 39) arr.shift();
saveCloseArray(arr);
}
}, [newItem]); // <--- I need to add closeArray but it will make a yucky loop
依赖数组中,则会出现错误...
closeArray
如果我不将useEffect
添加到index.js:1 Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
in App (at src/index.tsx:9)
in StrictMode (at src/index.tsx:8)
依赖数组中,则会出现此错误...
closeArray
第二个useEffect
块获取React Hook useEffect has a missing dependency: 'closeArray'. Either include it or remove the dependency array react-hooks/exhaustive-deps
的初始数据,并侦听WebSocket,该WebSocket在到达useEffect
时对其进行更新。
closeArray
答案 0 :(得分:1)
为了更好地编写代码,您可以使用状态更新程序的回调方法,这样,即使您不将closeArray传递给useEffect,它也会在useEffect的每次运行中积累更新的值
function App() {
const [newItem, saveNewItem] = useState<CloseInterface>();
const [closeArray, saveCloseArray] = useState<CloseInterface[]>([]);
useEffect(() => {
if (newItem) {
let found = false;
saveCloseArray(prevCloseArray => {
let arr = [];
for (let i = 0; i < prevCloseArray.length; i++) {
if (prevCloseArray[i].openTime === newItem.openTime) {
found = true;
arr.push(newItem);
} else {
arr.push(prevCloseArray[i]);
}
}
if (found === false) {
arr.push(newItem)
}
if (arr.length === 39) arr.shift();
return arr;
})
}
}, [newItem]);
答案 1 :(得分:0)
您要使用useCallback
来保存带有更新项的新数组,如下所示:
const [closeArray, saveCloseArray] = useState<CloseInterface[]>([]);
const updateEntry = useCallback(newItem => {
saveCloseArray(oldCloseArray => oldCloseArray.reduce((acc, item) => {
acc.push(item.openTime === newItem.openTime ? newItem : item);
return acc;
}, []));
}, []);
然后将回调函数应用于按钮或div或正在生成的任何组件(例如EG)
return (
[1, 2, 3, 4, 5].map(item => <button key={`${item}`} onClick={() => updateEntry(item)}>Click me</button>)
);
答案 2 :(得分:0)
如果您拥有newItem
的唯一原因是更新closeArray
,则可以考虑将该功能移至利用WebSocket的useEffect
中。如果除了更新newItem
之外还需要执行其他操作,例如显示警报或弹出窗口,仍然可以使用closeArray
。这就是我的意思:
interface CloseInterface {
openTime: number;
closeTime: number;
close: number;
}
function App() {
const [newItem, saveNewItem] = useState<CloseInterface>();
const [closeArray, saveCloseArray] = useState<CloseInterface[]>([]);
useEffect(() => {
// Do something when newItem changes, e.g. show alert
if (newItem) {
}
}, [newItem]);
useEffect(() => {
// Work with the new item
const precessNewItem = (item = {}) => {
let found = false;
let arr = [];
for (let i = 0; i < closeArray.length; i++) {
if (closeArray[i].openTime === item.openTime) {
found = true;
arr.push(item);
} else {
arr.push(closeArray[i]);
}
}
if (found === false) {
arr.push(item)
}
if (arr.length === 39) arr.shift();
saveCloseArray(arr);
// save new item
saveNewItem(item);
};
const getDetails = async () => {
const params = new window.URLSearchParams({
symbol: symbol.toUpperCase(),
interval
});
const url = `https://api.binance.com/api/v3/klines?${params}&limit=39`;
const response = await fetch(url, { method: "GET" });
const data = await response.json();
if (data) {
const arrayLength = data.length;
let newcloseArray = [];
for (var i = 0; i < arrayLength; i++) {
const openTime = data[i][0];
const closeTime = data[i][6];
const close = data[i][4];
newcloseArray.push({ openTime, closeTime, close });
}
saveCloseArray(newcloseArray);
const ws = new WebSocket("wss://stream.binance.com:9443/ws");
ws.onopen = () =>
ws.send(
JSON.stringify({
method: "SUBSCRIBE",
params: [`${symbol}@kline_${interval}`],
id: 1
})
);
ws.onmessage = e => {
const data = JSON.parse(e.data);
const value = data.k;
if (value) {
const openTime = value.t;
const closeTime = value.T;
const close = value.c;
// process new item
processNewItem({ openTime, closeTime, close });
}
};
}
};
getDetails();
}, [symbol, interval, closeArray]); // add closeArray here
}