React 中使用的条件
Conditions in useEffect React
我有一个 useEffect 在启动时订阅 websocket 并将来自服务器的数据添加到 operationList 列表。该列表显示在网页上。这是施工设备执行的操作列表,我在网上收到,无法在后端更改。
useEffect(() => {
const ws = new WebSocket('ws://127.0.0.1:8000/ws/')
ws.addEventListener('message', (e) => {
const response = JSON.parse(e.data)
setOperationsList(operationsList => [
response,
...operationsList,
]);
})
ws.onopen = () => {
ws.send(JSON.stringify({
action: "subscribe_to_operations_activity",
request_id: new Date().getTime(),
}))
}
}, [])
在同一个组件中,我有一个状态,它存储有关设备 ID 的信息,当前显示在屏幕上的报告。
const [activeID, setActiveID] = useState(false)
我需要向 operationsList 添加的不是服务器中的所有数据,就像现在所做的那样 response = JSON.parse(e.data).相反,我需要检查条件 response.id == activeID,并仅将满足条件的数据添加到 operationsList。我无法将 activeID 添加到 useEffect 依赖项列表中,因为在这种情况下,每次 activeID 更改时都会创建一个新的 WebSocket 订阅。我知道很可能我不了解一些基本的东西,所以我将不胜感激任何建议
添加了 activeID 路径:
在我的组件中
const [activeID, setActiveID] = useState(false)
const getElementStar = (newID) => {
setActiveID(newID)
}
然后我将它作为 props 传递给子组件:
<LeftMenu
...
getElementStar={getElementStar}
...
/>
最后在子组件中
const getKey = () => {
const newID = props.item.id
props.getElementStar(newID)
}
return (
<ListItemButton sx={{ pl: 4 }} key={props.index} onClick={getKey}>
<ListItemIcon>
{ props.star === props.index ? <Star/> : <StarBorder/> }
</ListItemIcon>
<ListItemText primary={props.item.name} />
</ListItemButton>
);
您可以尝试 运行 一个带有条件的循环,一旦为真,就会将您想要推送的内容推送到特定列表。仅当您从 back-end 接收的数据是一种数组类型时才有效。
let dataList = []
const loopData = () => {
e.data.forEach((obj) => {
if (obj.id === activeID) {
dataList.push(obj)
}
}
}
useEffect(() => loopData(), []);
然后
setOperationsList(...dataList)
activeID
应该如何改变?
基本上,将某些东西存储在状态中意味着当此值更改时组件需要 re-render。哪一个似乎不是你的情况?
所以我建议将您的 activeID
存储为 ref
const activeID = useRef('[my id]')
useEffect(() => {
const ws = new WebSocket('ws://127.0.0.1:8000/ws/')
ws.addEventListener('message', (e) => {
const response = JSON.parse(e.data)
setOperationsList(operationsList => [
...response.filter(o => o.id === activeID.current),
...operationsList,
]);
})
ws.onopen = () => {
ws.send(JSON.stringify({
action: "subscribe_to_operations_activity",
request_id: new Date().getTime(),
}))
}
}, [])
如果 activeID 需要以某种方式更改,您可以通过
useEffect(() => {
activeID.current = [my new value]
}, [triggers that could change activeId (maybe a prop?)])
=== 编辑 ===
所以我假设更改 activeID
必须触发 re-render 以根据当前 activeID
更改您的 <Star >
组件,对吗? :)
所以我建议 2 个不同的东西。要么用ref
,要么就是这样
const [activeID, setActiveID] = useState();
const activeIDRef = useRef()
你 useEffect
有
ws.addEventListener('message', (e) => {
const response = JSON.parse(e.data)
setOperationsList(operationsList => [
...response.filter(o => o.id === activeIDRef.current),
...operationsList,
]);
})
并有第二个 useEffect
在 activeID
更改时更改 ref
useEffect(() => {
activeIDRef.current = activeID
}, [activeID])
或
也许继续将所有内容存储在 operationsList
中但在显示值时对其进行过滤会更容易。如果你需要这样的状态
const [operationsListFiltered, setOperationsListFiltered] = useState([]);
useEffect(() => {
setOperationsListFiltered(operationsList.filter(o => o.id === activeId))
}, [activeId, operationsList])
或直接作为变量
const operationsListFiltered = useMemo(() => operationsList.filter(o => o.id === activeId), [activeId, operationsList]);
这样,您的 activeID
或您的 websocket 中的 operationLists
发生变化,您的 operationsListFiltered
将被更新
我有一个 useEffect 在启动时订阅 websocket 并将来自服务器的数据添加到 operationList 列表。该列表显示在网页上。这是施工设备执行的操作列表,我在网上收到,无法在后端更改。
useEffect(() => {
const ws = new WebSocket('ws://127.0.0.1:8000/ws/')
ws.addEventListener('message', (e) => {
const response = JSON.parse(e.data)
setOperationsList(operationsList => [
response,
...operationsList,
]);
})
ws.onopen = () => {
ws.send(JSON.stringify({
action: "subscribe_to_operations_activity",
request_id: new Date().getTime(),
}))
}
}, [])
在同一个组件中,我有一个状态,它存储有关设备 ID 的信息,当前显示在屏幕上的报告。
const [activeID, setActiveID] = useState(false)
我需要向 operationsList 添加的不是服务器中的所有数据,就像现在所做的那样 response = JSON.parse(e.data).相反,我需要检查条件 response.id == activeID,并仅将满足条件的数据添加到 operationsList。我无法将 activeID 添加到 useEffect 依赖项列表中,因为在这种情况下,每次 activeID 更改时都会创建一个新的 WebSocket 订阅。我知道很可能我不了解一些基本的东西,所以我将不胜感激任何建议
添加了 activeID 路径:
在我的组件中
const [activeID, setActiveID] = useState(false)
const getElementStar = (newID) => {
setActiveID(newID)
}
然后我将它作为 props 传递给子组件:
<LeftMenu
...
getElementStar={getElementStar}
...
/>
最后在子组件中
const getKey = () => {
const newID = props.item.id
props.getElementStar(newID)
}
return (
<ListItemButton sx={{ pl: 4 }} key={props.index} onClick={getKey}>
<ListItemIcon>
{ props.star === props.index ? <Star/> : <StarBorder/> }
</ListItemIcon>
<ListItemText primary={props.item.name} />
</ListItemButton>
);
您可以尝试 运行 一个带有条件的循环,一旦为真,就会将您想要推送的内容推送到特定列表。仅当您从 back-end 接收的数据是一种数组类型时才有效。
let dataList = []
const loopData = () => {
e.data.forEach((obj) => {
if (obj.id === activeID) {
dataList.push(obj)
}
}
}
useEffect(() => loopData(), []);
然后
setOperationsList(...dataList)
activeID
应该如何改变?
基本上,将某些东西存储在状态中意味着当此值更改时组件需要 re-render。哪一个似乎不是你的情况?
所以我建议将您的 activeID
存储为 ref
const activeID = useRef('[my id]')
useEffect(() => {
const ws = new WebSocket('ws://127.0.0.1:8000/ws/')
ws.addEventListener('message', (e) => {
const response = JSON.parse(e.data)
setOperationsList(operationsList => [
...response.filter(o => o.id === activeID.current),
...operationsList,
]);
})
ws.onopen = () => {
ws.send(JSON.stringify({
action: "subscribe_to_operations_activity",
request_id: new Date().getTime(),
}))
}
}, [])
如果 activeID 需要以某种方式更改,您可以通过
useEffect(() => {
activeID.current = [my new value]
}, [triggers that could change activeId (maybe a prop?)])
=== 编辑 ===
所以我假设更改 activeID
必须触发 re-render 以根据当前 activeID
更改您的 <Star >
组件,对吗? :)
所以我建议 2 个不同的东西。要么用ref
,要么就是这样
const [activeID, setActiveID] = useState();
const activeIDRef = useRef()
你 useEffect
有
ws.addEventListener('message', (e) => {
const response = JSON.parse(e.data)
setOperationsList(operationsList => [
...response.filter(o => o.id === activeIDRef.current),
...operationsList,
]);
})
并有第二个 useEffect
在 activeID
更改时更改 ref
useEffect(() => {
activeIDRef.current = activeID
}, [activeID])
或
也许继续将所有内容存储在 operationsList
中但在显示值时对其进行过滤会更容易。如果你需要这样的状态
const [operationsListFiltered, setOperationsListFiltered] = useState([]);
useEffect(() => {
setOperationsListFiltered(operationsList.filter(o => o.id === activeId))
}, [activeId, operationsList])
或直接作为变量
const operationsListFiltered = useMemo(() => operationsList.filter(o => o.id === activeId), [activeId, operationsList]);
这样,您的 activeID
或您的 websocket 中的 operationLists
发生变化,您的 operationsListFiltered
将被更新