Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

128
Views
Conditions in useEffect React

I have a useEffect that subscribes to websocket at startup and adds the data that comes from the server to the operationList list. This list is displayed on the webpage. This is a list of operations performed by construction equipment, which I receive online and could not chage on a backend.

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(),
  }))
  }
}, [])  

In the same component I have a state, which stores information about the id of the equipment, the report on which is currently displayed on the screen.

const [activeID, setActiveID]  = useState(false)

I need to add to the operationsList not all the data that comes in the server, as it is done now response = JSON.parse(e.data). Instead, I need to check the condition response.id == activeID, and to add to operationsList only those data that satisfy the condition. I can't add activeID to the list of useEffect dependencies because in this case, a new WebSocket subscription will be created every time the activeID changes. I understand that most likely I don't understand some basic things, so I would be grateful for any advice

Added the activeID path:

In my component

const [activeID, setActiveID]  = useState(false)

  const getElementStar = (newID) => {
  setActiveID(newID)
}

Then I pass it to child component as props:

<LeftMenu
  ...
  getElementStar={getElementStar}
  ...
/>

And finally in child component

  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>
  );
about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

How activeID is supposed to change? Basically, storing something in a state implies that the component need a re-render when this value changes. Which does not seem to be your case here?

So I would suggest to have your activeID stored as a 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(),
  }))
  }
}, [])  

If activeID needs to change somehow, you can have this by doing

useEffect(() => {
    activeID.current = [my new value]
}, [triggers that could change activeId (maybe a prop?)])

=== EDIT ===

So I assume changing activeID must trigger a re-render to change your <Star > component depending on current activeID right? :)

So I would suggest 2 differents things. Either with the ref, so something like that

const [activeID, setActiveID] = useState();
const activeIDRef = useRef()

on your useEffect having

ws.addEventListener('message', (e) => {
    const response = JSON.parse(e.data)

      setOperationsList(operationsList => [
      ...response.filter(o => o.id === activeIDRef.current),
      ...operationsList,
    ]);
})

and have a second useEffect to change ref when activeID changes

useEffect(() => {
    activeIDRef.current = activeID
}, [activeID])

OR

Maybe it would be easier to keep on storing everything in your operationsList BUT having it filtered when displaying values. If you need it in a state, like this

const [operationsListFiltered, setOperationsListFiltered] = useState([]);
useEffect(() => {
    setOperationsListFiltered(operationsList.filter(o => o.id === activeId))
}, [activeId, operationsList])

Or directly as variable

const operationsListFiltered = useMemo(() => operationsList.filter(o => o.id === activeId), [activeId, operationsList]);

This way, either your activeID OR your operationLists from your websocket changes, your operationsListFiltered will be updated

about 4 years ago · Juan Pablo Isaza Report

0

You can try running a loop with a condition that, once true, will then push what you want to push to the specific list. That will only work if the data you are receiving from the back-end is a type of array.

let dataList = []

    const loopData = () => {
       e.data.forEach((obj) => {
         if (obj.id === activeID) {
            dataList.push(obj)
         } 
       }
    }

useEffect(() => loopData(), []);

And then

setOperationsList(...dataList)
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!