我正在嘗試使用狀態掛鉤在 ReactJS 中創建一個“物件的物件”,但我不確定如何根據傳入的資料動態創建它。
資料到達一個 websocket,我已經將它放在一個 Context 中,并且正在被相關組件使用。JSON 資料命中onmessage,它呼叫我的useEffect狀態掛鉤,然后呼叫一個函式來useState相應地更新變數。
入站 websocket 資料訊息一次進來一個,看起來像這樣(列出了重要的鍵,但里面有更多的道具):
{
"name": "PipelineA",
"state": "succeeded",
"group": "Group1"
}
{
"name": "PipelineE",
"state": "succeeded",
"group": "Group1"
}
{
"name": "PipelineZ",
"state": "succeeded",
"group": "Group4"
}
...其中nameandgroup是我想用來創建“物件物件”的值。因此,group將用于創建一組管道,這些管道都是同一組的一部分,在該物件中,每個管道的名稱將作為其整個資料的“鍵”。因此,“物件的物件”的最終狀態將如下所示:
{
"Group1": {
"PipelineA": {
"name": "PipelineA",
"state": "running",
"group": "Group1"
},
"PipelineB": {
"name": "PipelineB",
"state": "running",
"group": "Group1"
}
},
"Group2": {
"PipelineC": {
"name": "PipelineC",
"state": "running",
"group": "Group2"
},
"PipelineD": {
"name": "PipelineD",
"state": "running",
"group": "Group2"
}
},
...etc...
}
所以想法是,Group1 的管道將被添加到Group1物件中,如果PipelineA已經存在,它只是覆寫它,如果不存在,它會添加它。等等等等。
我(有點)可以在 React 之外用純 JS 做這件事,但我一輩子都無法弄清楚如何在 ReactJS 中做這件事。
const [groupedPipelineObjects, setGroupedPipelineObjects] = useState({});
const [socketState, ready, message, send] = useContext(WebsocketContext);
useEffect(() => {
if (message) {
updatePipelineTypeObjects(message)
}
}, [message]);
const updatePipelineGroupObjects = (data) => {
const pipelineName = data.name
const pipelineGroup = data.group
// let groupObj = {pipelineGroup: {}} // do I need to create it first?
setGroupedPipelineObjects(prevState => ({
...prevState,
[pipelineGroup]: {[pipelineName]: data} // <-- doesnt do what I need
}))
}
幫助或建議將不勝感激。僅供參考,管道名稱是唯一的,因此沒有重復,因此將它們用作鍵。
另外,我為什么要這樣做?我已經讓它與所有管道的一個物件一起作業,其中管道名稱是鍵,它的資料是值,然后呈現一個巨大的頁面或可擴展的表行。但我需要壓縮它并將組作為主要行,然后我將它們展開以顯示其中的管道。我認為這樣做會使渲染組件更容易。
uj5u.com熱心網友回復:
只是你走得還不夠遠。您所擁有的將完全替換該組,而不僅僅是添加或替換其中的相關管道。相反,如果有的話,復制并更新現有組:
const updatePipelineGroupObjects = (data) => {
const pipelineName = data.name;
const pipelineGroup = data.group;
// let groupObj = {pipelineGroup: {}} // do I need to create it first?
setGroupedPipelineObjects((prevState) => {
const groups = { ...prevState };
if (groups[pipelineGroup]) {
// Update the existing group with this pipeline,
// adding or updating it
groups[pipelineGroup] = {
...groups[pipelineGroup],
[pipelineName]: data,
};
} else {
// Add new group with this pipeline
groups[pipelineGroup] = {
[pipelineName]: data,
};
}
return groups;
});
};
此外,您正在嘗試在[]此處使用可迭代解構 ( ):
const [ socketState, ready, message, send ] = useContext(WebsocketContext);
但據我了解,您的背景關系物件是普通物件,而不是可迭代物件,因此您需要物件解構({}):
const { socketState, ready, message, send } = useContext(WebsocketContext);
現場示例:
顯示代碼片段
const { useState, useEffect, useContext } = React;
const WebsocketContext = React.createContext({ message: null });
const Example = () => {
const [groupedPipelineObjects, setGroupedPipelineObjects] = useState({});
const { socketState, ready, message, send } = useContext(WebsocketContext);
useEffect(() => {
if (message) {
updatePipelineGroupObjects(message);
}
}, [message]);
const updatePipelineGroupObjects = (data) => {
const pipelineName = data.name;
const pipelineGroup = data.group;
// let groupObj = {pipelineGroup: {}} // do I need to create it first?
setGroupedPipelineObjects((prevState) => {
const groups = { ...prevState };
if (groups[pipelineGroup]) {
// Update the existing group with this pipeline,
// adding or updating it
groups[pipelineGroup] = {
...groups[pipelineGroup],
[pipelineName]: data,
};
} else {
// Add new group with this pipeline
groups[pipelineGroup] = {
[pipelineName]: data,
};
}
return groups;
});
};
return <pre>{JSON.stringify(groupedPipelineObjects, null, 4)}</pre>;
};
// Mocked messages from web socket
const messages = [
{
name: "PipelineA",
state: "succeeded",
group: "Group1",
},
{
name: "PipelineB",
state: "running",
group: "Group1",
},
{
name: "PipelineC",
state: "running",
group: "Group2",
},
{
name: "PipelineD",
state: "running",
group: "Group2",
},
{
name: "PipelineE",
state: "succeeded",
group: "Group1",
},
{
name: "PipelineZ",
state: "succeeded",
group: "Group4",
},
];
const App = () => {
const [fakeSocketContext, setFakeSocketContext] = useState({ message: null });
useEffect(() => {
let timer = 0;
let index = 0;
tick();
function tick() {
const message = messages[index];
if (message) {
setFakeSocketContext({ message });
index;
timer = setTimeout(tick, 800);
}
}
return () => {
clearTimeout(timer);
};
}, []);
return (
<WebsocketContext.Provider value={fakeSocketContext}>
<Example />
</WebsocketContext.Provider>
);
};
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/520854.html
