Tengo un useEffect que se suscribe a websocket al inicio y agrega los datos que provienen del servidor a la lista de OperationList . Esta lista se muestra en la página web. Esta es una lista de operaciones realizadas por equipos de construcción, que recibo en línea y no pude cambiar en un servidor.
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(), })) } }, [])En el mismo componente tengo un estado, que almacena información sobre la identificación del equipo, cuyo informe se muestra actualmente en la pantalla.
const [activeID, setActiveID] = useState(false)Necesito agregar a la lista de operaciones no todos los datos que vienen en el servidor, ya que se hace ahora respuesta = JSON.parse(e.data) . En su lugar, necesito verificar la condición response.id == activeID y agregar a la lista de operaciones solo aquellos datos que satisfacen la condición. No puedo agregar activeID a la lista de dependencias de useEffect porque, en este caso, se creará una nueva suscripción de WebSocket cada vez que cambie el activeID . Entiendo que lo más probable es que no entienda algunas cosas básicas, por lo que agradecería cualquier consejo.
Se agregó la ruta de ActiveID :
En mi componente
const [activeID, setActiveID] = useState(false) const getElementStar = (newID) => { setActiveID(newID) }Luego lo paso al componente secundario como accesorios:
<LeftMenu ... getElementStar={getElementStar} ... />Y finalmente en el componente hijo.
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> );¿Cómo se supone que debe cambiar activeID ? Básicamente, almacenar algo en un estado implica que el componente necesita volver a renderizarse cuando cambia este valor. ¿Cuál no parece ser tu caso aquí?
Así que sugeriría tener su activeID almacenado como 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(), })) } }, [])Si activeID necesita cambiar de alguna manera, puede tener esto haciendo
useEffect(() => { activeID.current = [my new value] }, [triggers that could change activeId (maybe a prop?)])=== EDITAR ===
Así que asumo que cambiar activeID debe desencadenar una nueva representación para cambiar su componente <Star > dependiendo del ID activo actual activeID verdad? :)
Así que sugeriría 2 cosas diferentes. Ya sea con el ref , así que algo así
const [activeID, setActiveID] = useState(); const activeIDRef = useRef() en su useEffect tener
ws.addEventListener('message', (e) => { const response = JSON.parse(e.data) setOperationsList(operationsList => [ ...response.filter(o => o.id === activeIDRef.current), ...operationsList, ]); }) y tener un segundo useEffect de uso para cambiar la referencia cuando cambia activeID
useEffect(() => { activeIDRef.current = activeID }, [activeID])O
Tal vez sería más fácil seguir almacenando todo en su lista de operationsList PERO tenerlo filtrado al mostrar valores. Si lo necesitas en un estado, como este
const [operationsListFiltered, setOperationsListFiltered] = useState([]); useEffect(() => { setOperationsListFiltered(operationsList.filter(o => o.id === activeId)) }, [activeId, operationsList])O directamente como variable
const operationsListFiltered = useMemo(() => operationsList.filter(o => o.id === activeId), [activeId, operationsList]); De esta manera, ya sea su activeID O sus listas de operationLists de su websocket cambia, su lista de operationsListFiltered filtradas se actualizará
Puede intentar ejecutar un bucle con una condición que, una vez que sea cierta, enviará lo que desea enviar a la lista específica. Eso solo funcionará si los datos que recibe del back-end son un tipo de matriz.
let dataList = [] const loopData = () => { e.data.forEach((obj) => { if (obj.id === activeID) { dataList.push(obj) } } } useEffect(() => loopData(), []);Y entonces
setOperationsList(...dataList)